CSU 1532 JuQueen 线段树 lazy 区间最值

题目链接:点击打开链接

题意:

第一行给出C, n, Q

开始有一个编号[0, C) 的全0序列。

下面Q行操作

status id (询问下标为id的值)

groupchange [l, r] val  把区间[l,r] 每次+1(或-1)val次,当区间中某一个点达到0或n时则操作停止,输出实际+1(或-1)的值

change id val 同上,只是单点操作。

思路:

裸线段树,维护区间最值和加个lazy标记就可以了



#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>

template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if(c=getchar(),c==EOF) return 0;
	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='-')?-1:1;
	ret=(c=='-')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
	ret*=sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int N = 50500;
const int inf = 1e8;
#define L(x) tree[x].l
#define R(x) tree[x].r
#define Max(x) tree[x].max
#define Min(x) tree[x].min
#define Lazy(x) tree[x].lazy
#define ls (id<<1)
#define rs (id<<1|1)
struct Node{
	int l, r, min, max, lazy;
}tree[N<<4];
void Up(int id){
	Max(id) = max(Max(ls), Max(rs));
	Min(id) = min(Min(ls), Min(rs));
}
void Down(int id){
	if(Lazy(id)){
		Min(ls) += Lazy(id);
		Min(rs) += Lazy(id);
		Max(ls) += Lazy(id);
		Max(rs) += Lazy(id);
		Lazy(ls) += Lazy(id);
		Lazy(rs) += Lazy(id);
		Lazy(id) = 0;
	}
}
void build(int l, int r, int id){
	L(id) = l; R(id) = r;
	Min(id) = Max(id) = 0;
	Lazy(id) = 0;
	if(l == r)return ;
	int mid = (l+r)>>1;
	build(l, mid, ls); build(mid+1, r, rs);
}
void updata(int l, int r, int val, int id){
	if(l == L(id) && R(id) == r){
		Max(id) += val;
		Min(id) += val;
		Lazy(id) += val;
		return ;
	}
	Down(id);
	int mid = (L(id) + R(id))>>1;
	if(r <= mid)
		updata(l, r, val, ls);
	else if(mid < l)
		updata(l, r, val, rs);
	else {
		updata(l, mid, val, ls);
		updata(mid+1, r, val, rs);
	}
	Up(id);
}
int query_max(int l, int r, int id){
	if(l == L(id) && R(id) == r)return Max(id);
	Down(id);
	int mid = (L(id)+R(id))>>1, ans;
	if(r <= mid) ans = query_max(l, r, ls);
	else if(mid < l) ans = query_max(l, r, rs);
	else ans = max(query_max(l, mid, ls), query_max(mid+1, r, rs));
	Up(id);
	return ans;
}
int query_min(int l, int r, int id){
	if(l == L(id) && R(id) == r)return Min(id);
	Down(id);
	int mid = (L(id)+R(id))>>1, ans;
	if(r <= mid) ans = query_min(l, r, ls);
	else if(mid < l) ans = query_min(l, r, rs);
	else ans = min(query_min(l, mid, ls), query_min(mid+1, r, rs));
	Up(id);
	return ans;
}

int C, n, q;
struct Q{
	char op;
	int l, r, x;
	void put(){printf("  (%c, %d, %d, %d)\n", op, l, r, x);}
}o[50500];
char s[20];
vector<int>G;
void input(){
	G.clear();
	for(int i = 0; i < q; i++)
	{
		scanf("%s", s);
		o[i].op = s[0];
		if(s[0] == 's')rd(o[i].l);
		else if(s[0] == 'g'){
			rd(o[i].l); rd(o[i].r); rd(o[i].x);
			G.push_back(o[i].r);
		}
		else {
			o[i].op = 'g';
			rd(o[i].l); rd(o[i].x);
			o[i].r = o[i].l;
		}
		G.push_back(o[i].l);
  	}
  	sort(G.begin(), G.end());
  	G.erase(unique(G.begin(), G.end()), G.end());
  	for(int i = 0; i < q; i++){
  		o[i].l = lower_bound(G.begin(), G.end(), o[i].l) - G.begin()+1;
  		if(o[i].op == 'g')
  			o[i].r = lower_bound(G.begin(), G.end(), o[i].r) - G.begin()+1;
  	}
  //	for(int i = 0; i < q; i++)o[i].put();
}
int main(){
	int T;
    while(~scanf("%d%d%d", &C, &n, &q)){
   // 	printf("---%d,%d,%d\n", C, n, q);
    	input();
	  	build(1, (int)G.size(), 1);
	  	int l, r, x, tmp; char c;
	  	for(int i = 0; i < q; i++){
			c = o[i].op; l = o[i].l; r = o[i].r; x = o[i].x;
	  		if(c == 's')
				pt(query_min(l, l, 1));
			else if(c == 'g')
			{
				if(x == 0){puts("0");continue;}
				else if(x > 0){
					tmp = query_max(l, r, 1);
		//			printf("max:%d\n", tmp);
					x = min(x, n - tmp);
				}
				else {
					tmp = query_min(l, r, 1);
		//			printf("min:%d\n", tmp);
					x = max(x, -tmp);
				}
				updata(l, r, x, 1);
				pt(x);
			}
	  		putchar('\n');
	  	}
    }
    return 0;
}


你可能感兴趣的:(CSU 1532 JuQueen 线段树 lazy 区间最值)