const int Max_N = 50100 ; int sum[Max_N<<2] , x[Max_N] ; void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ; } void make_tree(int L , int R , int root){ if(L == R){ sum[root] = x[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ; } void update(int id , int c , int L , int R , int root){ if(L == R){ sum[root] += c ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , c , L , mid ,root<<1) ; else update(id , c , mid+1 , R , root<<1|1) ; push_up(root) ; } int query(int l , int r , int L , int R ,int root){ if(l <= L && R <= r) return sum[root] ; int mid = (L + R) >> 1 ; int ans = 0 ; if(l <= mid) ans += query(l , r , L , mid , root<<1) ; if(r > mid) ans += query(l , r , mid+1 , R , root<<1|1) ; return ans ; } int main(){ int T , n , i , a , b ; char str[8] ; cin>>T ; for(int cas = 1 ; cas <= T ; cas++){ printf("Case %d:\n",cas) ; scanf("%d",&n) ; for(i = 1 ; i <= n ; i++) scanf("%d",&x[i]) ; make_tree(1,n,1) ; while(scanf("%s",str) && strcmp(str,"End")!=0){ scanf("%d%d",&a,&b) ; if(str[0] == 'A') update(a , b , 1 , n , 1) ; else if(str[0] == 'S') update(a , -b , 1 , n , 1) ; else printf("%d\n",query(a , b , 1 , n , 1)) ; } } return 0 ; }
const int Max_N = 5008 ; int Sum[Max_N<<1] ,x[Max_N]; void push_up(int root){ Sum[root] = Sum[root<<1] + Sum[root<<1|1] ; } void make_tree(int L , int R , int root){ if(L == R){ Sum[root] = 0 ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ; } void update(int id , int L , int R , int root){ if(L == R){ Sum[root]++ ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , L , mid , root<<1) ; else update(id , mid+1 , R , root<<1|1) ; push_up(root) ; } int query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return Sum[root] ; int mid = (L + R) >> 1 ; int ans = 0 ; if(l <= mid) ans += query(l , r , L , mid , root<<1) ; if(r > mid) ans += query(l , r , mid+1 , R , root<<1|1) ; return ans ; } int main(){ int n , i , sum , ans ; while(cin>>n){ make_tree(1 , n , 1) ; //建一颗空树 sum = 0 ; for(i = 1 ; i <= n ; i++){ scanf("%d",&x[i]) ; x[i]++ ; // 序列变为[1,n] sum += query(x[i] , n , 1 , n , 1) ; // [x[i] , n]出现的个数之和 , 也就是在大于x[i],且位置在起左边的个数 update(x[i] , 1 , n , 1) ; //在x[i]位置插入1 } ans = sum ; // sum即为初始序列逆序数 for(i = 1 ; i < n ; i++){ // 将想x[i]移到尾巴。逆序数变化情况。 x[i]在头少了(x[i] -1 ) ,x[i] 在尾多了(n-x[i])个 ,总计多了: +(n-x[i])-(x[i]-1) sum = sum + n - x[i] - x[i] + 1 ; ans = min(ans ,sum) ; } printf("%d\n",ans) ; } return 0 ; }
const int Max_N = 200100 ; int Max[Max_N<<2] , x[Max_N] ; void push_up(int root){ Max[root] = max(Max[root<<1] , Max[root<<1|1]) ; } void make_tree(int L , int R , int root){ if(L == R){ Max[root] = x[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ; } void update(int id , int c , int L , int R , int root){ if(L == R){ Max[root] = c ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , c , L , mid ,root<<1) ; else update(id , c , mid+1 , R ,root<<1|1) ; push_up(root) ; } int query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return Max[root] ; int mid = (L + R) >> 1 ; int ans = -1 ; if(l <= mid) ans = max(ans , query(l , r , L , mid , root<<1)) ; if(r > mid) ans = max(ans , query(l , r , mid+1 , R , root<<1|1)) ; return ans ; } int main(){ int n , m , i , a , b ; char str[2] ; while(cin>>n>>m){ for(i = 1 ; i <= n ; i++) scanf("%d",&x[i]) ; make_tree(1 , n , 1) ; while(m--){ scanf("%s%d%d",str,&a,&b) ; if(*str == 'U') update(a , b , 1 , n , 1) ; else printf("%d\n",query(a , b , 1 , n , 1)) ; } } return 0 ; }
POJ 4047 区间更新 , 区间最值
const int Max_N = 200010 ; int x[Max_N] , sum[Max_N] , num[Max_N] ; int N , K ; int _max[Max_N<<2] , add[Max_N<<2] ; void push_up(int root){ _max[root] = max(_max[root<<1] , _max[root<<1|1]) ; } void push_down(int root){ if(add[root]){ add[root<<1] += add[root] ; add[root<<1|1] += add[root] ; _max[root<<1] += add[root] ; _max[root<<1|1] += add[root] ; add[root] = 0 ; } } void make_tree(int L , int R , int root){ add[root] = 0 ; if(L == R){ _max[root] = num[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ; } void update(int l , int r , int c , int L , int R , int root){ if(l <= L && R <= r){ add[root] += c ; _max[root] += c ; return ; } push_down(root) ; int mid = (L + R) >> 1 ; if(l <= mid) update(l , r , c , L , mid , root<<1) ; if(r > mid) update(l , r , c , mid+1 , R , root<<1|1) ; push_up(root) ; } int query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return _max[root] ; push_down(root) ; int mid = (L + R) >> 1 ; int ans = -0xfffffff ; if(l <= mid) ans = max(ans, query(l , r , L , mid , root<<1) ) ; if(r > mid) ans = max(ans , query(l , r , mid+1 , R , root<<1|1) ); return ans ; } int main(){ int t , i , j , M , a , b , c , p ; scanf("%d" ,&t) ; while(t--){ scanf("%d%d%d" ,&N ,&M ,&K) ; sum[0] = 0 ; for(i = 1 ; i <= N ; i++){ scanf("%d" ,&x[i]) ; sum[i] = x[i] + sum[i-1] ; } for(i = K ; i <= N ; i++) num[i-K+1] = sum[i] - sum[i-K] ; N = N - K + 1 ; make_tree(1 , N , 1) ; while(M--){ scanf("%d%d%d" ,&p , &a , &b) ; if(p == 0){ if(x[a] != b){ c = b - x[a] ; x[a] = b ; update(max(a-K+1,1) , a , c , 1 , N , 1) ; } } else if(p == 1){ if(a != b){ c = x[b] - x[a] ; update(max(a-K+1,1) , a , c , 1 , N , 1) ; c = x[a] - x[b] ; update(max(b-K+1,1) , b , c , 1 , N , 1) ; swap(x[a] , x[b]) ; } } else{ printf("%d\n" , query(a, b-K+1 , 1 , N , 1)) ; } } } return 0 ; }
There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue. The i-th walrus has the age equal to ai.
The i-th walrus becomes displeased if there's a younger walrus standing in front of him, that is, if exists such j (i < j), that ai > aj. Thedispleasure of the i-th walrus is equal to the number of walruses between him and the furthest walrus ahead of him, which is younger than the i-th one. That is, the further that young walrus stands from him, the stronger the displeasure is.
The airport manager asked you to count for each of n walruses in the queue his displeasure.
The first line contains an integer n (2 ≤ n ≤ 105) — the number of walruses in the queue. The second line contains integers ai (1 ≤ ai ≤ 109).
Note that some walruses can have the same age but for the displeasure to emerge the walrus that is closer to the head of the queue needs to be strictly younger than the other one.
Print n numbers: if the i-th walrus is pleased with everything, print "-1" (without the quotes). Otherwise, print the i-th walrus's displeasure: the number of other walruses that stand between him and the furthest from him younger walrus.
6 10 8 5 3 50 45
2 1 0 -1 0 -1
7 10 4 6 3 2 8 15
4 2 1 0 -1 -1 -1
5 10 3 1 10 11
1 0 -1 -1 -1
题意:
有n个数的失望值,id失望值的定义是:id右边离它最远的且比它小的数 与 它本身之间 间隔的数的数量;
线段树,结点保存区间最小值 每次将当前的数更新为INF,然后查找整个区间内最右边的比它小的数的下标 .
const int Max_N = 100008 ; const int inf = 1000000800 ; int _Min[Max_N<<2] , x[Max_N] , ans[Max_N] ; void push_up(int root){ _Min[root] = min(_Min[root<<1] , _Min[root<<1|1]) ; } void make_tree(int L , int R , int root){ if(L == R){ _Min[root] = x[L] ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ; } void update(int id , int L , int R , int root){ if(L == R){ _Min[root] = inf ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , L , mid , root<<1) ; else update(id , mid+1 , R , root<<1|1) ; push_up(root) ; } //求区间[L,R]中 比C小 且 下标最大 的下标 。 其实二叉树遍历蛮重要的。 先右->后左。{好像不是3种遍历方式哦!} int query(int c , int L , int R , int root){ if(L == R) return L ; int mid = (L + R) >> 1 ; if(_Min[root<<1|1] < c) //右孩子的最小值比C小,则在右孩子中找 。 return query(c , mid+1 , R , root<<1|1) ; else return query(c , L , mid , root<<1) ; } int main(){ int n , i ; cin>>n ; for(i = 1 ; i <= n ; i++) scanf("%d" , &x[i]) ; make_tree(1 , n , 1) ; for(i = 1 ; i <= n ; i++){ update(i , 1 , n , 1) ; //将i处更新最大,更新完之后,_Min[1] = [1,n]最小值 if(_Min[1] < x[i]) ans[i] = query(x[i] , 1 , n , 1) - i - 1 ; // 为什么不能是query(x[i] , i , n , 1) ?因为[i,n]的节点编号不是1。注意这里 else ans[i] = -1 ; } printf("%d" , ans[1]) ; for(i = 2 ; i <= n ; i++) printf(" %d" , ans[i]) ; puts("") ; return 0 ; }
Just a Hook
typedef long long LL ; const int Max_N = 100008 ; int sum[Max_N<<2] ; /*和*/ int color[Max_N<<2] ;/*颜色,-1表示不是纯色*/ /*向上更新,计算和*/ void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ; } /*lazy操作,向下更新时,把纯色的颜色传递下去,同时更新和,若不是纯色则孩子节点的颜色之前已经更新*/ void push_down(int root ,int L ,int R){ if(color[root] != -1){ color[root<<1] = color[root<<1|1] = color[root] ; color[root] = -1 ; /*向下更新就是因为root节点不再纯色*/ int mid = (L+R)>>1 ; sum[root<<1] = (mid-L+1) * color[root<<1] ; sum[root<<1|1] = (R-mid) * color[root<<1|1] ; } } /*建树*/ void make_tree(int L , int R , int root){ color[root] = 1 ; if(L == R){ sum[root] = 1 ; return ; } int mid = (L+R)>>1 ; make_tree(L,mid,root<<1) ; make_tree(mid+1,R,root<<1|1) ; push_up(root) ; } /*更新区间[l,r]颜色为c*/ void update(int l , int r , int c ,int L ,int R ,int root){ if(l <= L && R <= r){ color[root] = c ; sum[root] = (R-L+1) * c ; return ; } push_down(root,L,R) ; int mid = (L+R)>>1 ; if(l <= mid) update(l,r,c,L,mid,root<<1) ; if(r > mid) update(l,r,c,mid+1,R,root<<1|1) ; push_up(root) ; } int main(){ int T ,cas , n ,q , l ,r ,c; scanf("%d",&T) ; for(cas = 1 ; cas <= T ; cas++){ scanf("%d",&n) ; make_tree(1,n,1) ; scanf("%d",&q) ; while(q--){ scanf("%d%d%d",&l,&r,&c) ; update(l,r,c,1,n,1) ; } printf("Case %d: The total value of the hook is %d.\n",cas,sum[1]) ; } return 0 ; }
区间【L, R】染色c ,每个点都取最大值。
求整个区间最大和。
const int Max_N = 50008 ; int color[Max_N<<2] ; void push_down(int root){ if(color[root] != -1){ color[root<<1] = max(color[root<<1],color[root]) ; color[root<<1|1] = max(color[root<<1|1],color[root]) ; color[root] = -1 ; } return ; } void make_tree(int L , int R , int root){ color[root] = 0 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; } void update(int l , int r , int c , int L , int R , int root){ if(l <= L && R <= r){ if(color[root] < c) color[root] = c ; return ; } push_down(root) ; int mid = (L + R) >> 1 ; if(l <= mid) update(l , r , c , L , mid , root<<1) ; if(r > mid) update(l , r , c , mid+1 , R , root<<1|1) ; } int query(int L , int R , int root){ if(L == R) return color[root] ; push_down(root) ; int mid = (L + R) >> 1 ; return query(L , mid , root<<1) + query(mid+1 , R ,root<<1|1) ; } int main(){ int n , m , l , r , c ; while(scanf("%d%d" ,&n ,&m) != EOF){ make_tree(0 , n , 1) ; while(m--){ l = getint() ; r = getint() ; c = getint() ; if(c) update(l , r-1 , c , 0 , n , 1) ; } printf("%d\n" , query(0 , n , 1)) ; } return 0 ; }
Time Limit: 5000MS | Memory Limit: 131072K | |
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
typedef long long LL ; const int Max_N = 101000 ; LL sum[Max_N<<2] , add[Max_N<<2] , x[Max_N]; void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ; } void push_down(int L ,int R ,int root){ if(add[root]){ //纯色才向下更新。 add[root<<1] += add[root] ; add[root<<1|1] += add[root] ; int mid = (L + R)>>1 ; sum[root<<1] += add[root]*(mid-L+1) ; sum[root<<1|1] += add[root]*(R-mid) ; add[root] = 0 ; //更新完便不再是纯色了。 } } void make_tree(int L ,int R,int root){ add[root] = 0 ; if(L == R){ sum[root] = x[L] ; return ; } int mid = (L + R)>>1 ; make_tree(L,mid,root<<1) ; make_tree(mid+1,R,root<<1|1) ; push_up(root) ; } void update(int l ,int r ,LL c ,int L ,int R ,int root){ if(l <= L && R <= r){ add[root] += c ; sum[root] += c*(R-L+1) ; return ; } push_down(L,R,root) ; int mid = (L + R)>>1 ; if(l <= mid) update(l,r,c,L,mid,root<<1) ; if(r > mid) update(l,r,c,mid+1,R,root<<1|1) ; push_up(root) ; } LL query(int l ,int r ,int L ,int R ,int root){ if(l <= L && R <= r) return sum[root] ; push_down(L,R,root) ; // update中push_down的时候并没有把所有该更新的更新完。 int mid = (L + R)>>1 ; LL ans = 0 ; if(l <= mid) ans += query(l,r,L,mid,root<<1) ; if(r > mid) ans += query(l,r,mid+1,R,root<<1|1) ; return ans ; } int main(){ int i , n , q ,l,r; LL c; char str[2] ; cin>>n>>q ; for(i = 1 ; i <= n ; i++) scanf("%lld",&x[i]) ; make_tree(1,n,1) ; while(q--){ scanf("%s%d%d",str,&l,&r) ; if(str[0] == 'Q') printf("%lld\n",query(l,r,1,n,1)) ; else{ scanf("%lld",&c) ; update(l,r,c,1,n,1) ; } } return 0 ; }
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
typedef long long LL ; const int Max_N = 100100 ; LL sum[Max_N<<2] , x[Max_N] ; int color[Max_N<<2] ; void push_up(int root){ sum[root] = sum[root<<1] + sum[root<<1|1] ; color[root] = color[root<<1] && color[root<<1|1] ; } void make_tree(int L , int R , int root){ if(L == R){ sum[root] = x[L] ; color[root] = sum[root] == 1 ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; push_up(root) ; } void update(int l , int r , int L , int R , int root){ if(color[root]) return ; if(L == R){ sum[root] = LL (sqrt(sum[root])) ; color[root] = sum[root] == 1 ; return ; } int mid = (L + R) >> 1 ; if(l <= mid) update(l , r , L , mid , root<<1) ; if(r > mid) update(l , r , mid+1 , R , root<<1|1) ; push_up(root) ; } LL query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return sum[root] ; int mid = (L + R) >> 1 ; LL ans = 0 ; if(l <= mid) ans += query(l , r , L , mid , root<<1) ; if(r > mid) ans += query(l , r , mid+1 , R , root<<1|1) ; return ans ; } int main(){ int n , i , q , k = 1 , t , l , r; while(cin>>n){ printf("Case #%d:\n" , k++) ; for(i = 1 ; i <= n ; i++) scanf("%I64d",&x[i]) ; make_tree(1 , n , 1) ; scanf("%d",&q) ; while(q--){ scanf("%d%d%d",&t,&l,&r) ; if(l > r) swap(l , r) ; if(t) printf("%I64d\n",query(l , r , 1 , n , 1)) ; else update(l , r , 1 , n , 1) ; } puts("") ; } return 0 ; }
题目大意:两个数组,a和b,两种操作:
1:将数组a的区间[x,x+k-1]复制给数组b的区间[y,y+k-1]。
2:问当前b[x]的值。
const int Max_N = 100008 ; int Pos[Max_N<<2] ; //区间左端映射到数组A下标的起点 void push_down(int root , int L , int R){ if(Pos[root]){ int mid = (L + R) >> 1 ; Pos[root<<1] = Pos[root] ; Pos[root<<1|1] = mid + 1 + Pos[root] - L ; Pos[root] = 0 ; } } void make_tree(int L , int R , int root){ Pos[root] = 0 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; } void update(int l , int r , int start , int L , int R , int root){ if(l == L && R == r){ Pos[root] = start ; return ; } push_down(root , L , R) ; int mid = (L + R) >> 1 ; if(r <= mid) update(l , r , start , L , mid , root<<1) ; else if(l > mid) update(l , r , start , mid+1 , R , root<<1|1) ; else{ update(l , mid , start , L , mid , root<<1) ; update(mid+1 , r , start+mid+1-l , mid+1 , R ,root<<1|1) ; } } int query(int id , int L , int R , int root){ if(L == R) return Pos[root] ; push_down(root , L , R) ; int mid = (L + R) >> 1 ; if(id <= mid) return query(id , L , mid , root<<1) ; else return query(id , mid+1 , R , root<<1|1) ; } int A[Max_N] , B[Max_N] ; int main(){ int i ,t , n , m , x , y , k; cin>>n>>m ; for(i = 1 ; i <= n ; i++) scanf("%d" , &A[i]) ; for(i = 1 ; i <= n ; i++) scanf("%d" , &B[i]) ; make_tree(1 , n , 1) ; while(m--){ scanf("%d%d" , &t , &x) ; if(t == 1){ scanf("%d%d" , &y , &k) ; update(y , y+k-1 , x , 1 , n , 1) ; } else{ int id = query(x , 1 , n , 1) ; printf("%d\n" , id ? A[id] : B[x]) ; } } return 0 ; }
const int Max_N = 1000008 ; int color[Max_N<<2] , final_color[Max_N] ; void push_down(int root){ if(color[root]){ color[root<<1] = color[root<<1|1] = color[root] ; color[root] = 0 ; } } void make_tree(int L , int R , int root){ color[root] = 0 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; } void update(int l , int r , int c , int L , int R , int root){ if(l <= L && R <= r){ color[root] = c ; return ; } push_down(root) ; int mid = (L + R) >> 1 ; if(l <= mid) update(l , r , c , L , mid , root<<1) ; if(r > mid) update(l , r , c , mid+1 , R , root<<1|1) ; } void query(int L , int R , int root){ if(L == R){ final_color[L] = color[root] ; return ; } push_down(root) ; int mid = (L + R) >> 1 ; query(L , mid , root<<1) ; query(mid+1 , R , root<<1|1) ; } int Ans(int N){ int ans = 0 ; int now = final_color[1] , num = 1 ; for(int i = 2 ; i <= N ; i++){ if(final_color[i] == now) num++ ; else{ if(now) ans = max(ans , num) ; now = final_color[i] ; num = 1 ; } } if(now) ans = max(ans , num) ; return ans ; } int main(){ int n , m , i , l , r; while(scanf("%d%d" , &n ,&m) != EOF){ make_tree(1 , n , 1) ; for(i = 1 ; i <= m ; i++){ scanf("%d%d" , &l , &r) ; if(l > r) swap(l , r) ; update(l , r , i , 1 , n , 1) ; } query(1 , n , 1) ; printf("%d\n" , Ans(n)) ; } return 0 ; }
输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
const int Max_N = 55558 ; int l_can[Max_N<<2] , r_can[Max_N<<2] , all_can[Max_N<<2] , color[Max_N<<2] ; void make_tree(int L , int R , int root){ l_can[root] = r_can[root] = all_can[root] = R - L + 1 ; color[root] = -1 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; } void push_down(int L , int R , int root){ if(color[root] != -1){ color[root<<1] = color[root<<1|1] = color[root] ; int mid = (L + R) >> 1 ; l_can[root<<1] = r_can[root<<1] = all_can[root<<1] = (color[root] ? mid-L+1 : 0) ; l_can[root<<1|1] = r_can[root<<1|1] = all_can[root<<1|1] = (color[root] ? R - mid : 0) ; color[root] = -1 ; } } void push_up(int L , int R , int root){ l_can[root] = l_can[root<<1] ; r_can[root] = r_can[root<<1|1] ; int mid = (L + R) >> 1 ; if(l_can[root] == mid - L + 1) l_can[root] += l_can[root<<1|1] ; if(r_can[root] == R - mid) r_can[root] += r_can[root<<1] ; all_can[root] = max(max(all_can[root<<1] , all_can[root<<1|1]) , r_can[root<<1] + l_can[root<<1|1]) ; } void update(int l , int r , int c , int L , int R , int root){ if(l <= L && R <= r){ l_can[root] = r_can[root] = all_can[root] = (c? R-L+1 : 0) ; color[root] = c ; return ; } push_down(L , R , root) ; int mid = (L + R) >> 1 ; if(l <= mid) update(l , r ,c , L , mid , root<<1) ; if(r > mid) update(l , r ,c , mid+1 , R , root<<1|1) ; push_up(L , R , root) ; } int query(int len , int L , int R , int root){ if(L == R) return L ; push_down(L , R , root) ; int mid = (L + R) >> 1 ; if(len <= all_can[root<<1]) return query(len , L , mid , root<<1) ; else if(len <= r_can[root<<1]+ l_can[root<<1|1]) return mid - r_can[root<<1] + 1 ; else return query(len , mid+1 , R , root<<1|1) ; } int main(){ int n , m , k , x , y , id ; scanf("%d%d" ,&n , &m) ; make_tree(1 , n , 1) ; while(m--){ scanf("%d%d" ,&k ,&x) ; if(k == 1){ if(all_can[1] < x) puts("0") ; else{ id = query(x , 1 , n , 1) ; printf("%d\n" ,id) ; update(id , id + x -1 , 0 , 1 , n , 1) ; } } else{ scanf("%d" , &y) ; update(x , x+y-1 , 1 , 1 , n , 1) ; } } return 0 ; }
题目大意:
有一条长度为L的街道,有N个操作,操作有两种:
(1)"1 a",表示有一辆长度为a的车开进来想找停车位;
停车位必须满足与它前面的车距离至少为b,与后面的车距离至少为f;
如果能找到这样的停车位;输出这辆车的起始位置(且这个位置最小),否则输出-1;
(2)"2 a",表示第a个事件里进来停车的那辆车开出去了;
算法思想:
建立起点为-b,终点为L+f的线段树;
查找的时候,直接查找len+b+f的线段就可以了;
注意这里存的是坐标点个数,而不是线段长度。
1 //节点个数 2 const int Max_N = 100300 ; 3 int L_canuse[Max_N<<2] , R_canuse[Max_N<<2] , All_canuse[Max_N<<2] , color[Max_N<<2] ; 4 5 void make_tree(int L , int R , int root){ 6 L_canuse[root] = R_canuse[root] = All_canuse[root] = R - L + 1 ; 7 color[root] = -1 ; 8 if(L == R) 9 return ; 10 int mid = (L + R) >> 1 ; 11 make_tree(L , mid , root<<1) ; 12 make_tree(mid+1 , R , root<<1|1) ; 13 } 14 15 void push_up(int root , int L , int R){ 16 L_canuse[root] = L_canuse[root<<1] ; 17 R_canuse[root] = R_canuse[root<<1|1] ; 18 int mid = (L + R) >> 1 ; 19 if(L_canuse[root] == mid - L + 1) 20 L_canuse[root] += L_canuse[root<<1|1] ; 21 if(R_canuse[root] == R - mid) 22 R_canuse[root] += R_canuse[root<<1] ; 23 All_canuse[root] = max(max(All_canuse[root<<1] , All_canuse[root<<1|1]), 24 R_canuse[root<<1] + L_canuse[root<<1|1]) ; 25 } 26 27 void push_down(int root , int L , int R){ 28 if(color[root] != -1){ 29 color[root<<1] = color[root<<1|1] = color[root] ; 30 int mid = (L + R) >> 1 ; 31 L_canuse[root<<1] = R_canuse[root<<1] = All_canuse[root<<1] = (color[root]? mid - L + 1 : 0) ; 32 L_canuse[root<<1|1] = R_canuse[root<<1|1] = All_canuse[root<<1|1] = (color[root]? R - mid : 0) ; 33 color[root] = -1 ; 34 } 35 } 36 37 void update(int l , int r , int c , int L , int R , int root){ 38 if(l <= L && R <= r){ 39 L_canuse[root] = R_canuse[root] = All_canuse[root] = (c? R - L + 1 : 0) ; 40 color[root] = c ; 41 return ; 42 } 43 push_down(root , L , R) ; 44 int mid = (L + R) >> 1 ; 45 if(l <= mid) 46 update(l , r , c , L , mid , root<<1) ; 47 if(r > mid) 48 update(l , r , c , mid+1 , R , root<<1|1) ; 49 push_up(root , L , R) ; 50 } 51 52 int query(int x , int L , int R , int root){ 53 if(L == R) 54 return L ; 55 push_down(root , L , R) ; 56 int mid = (L + R) >> 1 ; 57 if(x <= All_canuse[root<<1]) 58 return query(x , L , mid , root<<1) ; 59 else if(x <= R_canuse[root<<1] + L_canuse[root<<1|1]) 60 return mid - R_canuse[root<<1] + 1 ; 61 else 62 return query(x , mid+1 , R , root<<1|1) ; 63 } 64 65 struct Car{ 66 int Start ; 67 int Len ; 68 }car[108]; 69 70 int main(){ 71 int n ,L , B , F , t , x ; 72 cin>>L>>B>>F; 73 make_tree(-B , L+F , 1) ; 74 cin>>n ; 75 for(int i = 1 ; i <= n ; i++){ 76 cin>>t>>x ; 77 if(t == 1){ 78 car[i].Len = x ; 79 if(All_canuse[1] < x + B + F + 1) 80 puts("-1") ; 81 else{ 82 car[i].Start = query(x+B+F , -B , L+F , 1) + B ; 83 update(car[i].Start , car[i].Start + car[i].Len - 1, 0 , -B , L+F , 1) ; 84 printf("%d\n",car[i].Start) ; 85 } 86 } 87 else 88 update(car[x].Start , car[x].Start + car[x].Len - 1 , 1 , -B , L+F , 1) ; 89 } 90 return 0 ; 91 }
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3609 Accepted Submission(s): 1377
/*区间合并*/ typedef long long LL ; const int Max_N = 50100 ; /*Left[i] ,到节点i左端点连续村庄的个数 ,Right[i] ,到节点i右端点连续村庄的个数 */ int Left[Max_N<<2] , Right[Max_N<<2] ; void push_up(int L , int R , int root){ Left[root] = Left[root<<1] ; Right[root] = Right[root<<1|1] ; int mid = (L + R) >> 1 ; if(Left[root] == mid - L + 1) Left[root] += Left[root<<1|1] ; if(Right[root] == R - mid) Right[root] += Right[root<<1] ; } void make_tree(int L ,int R ,int root){ Left[root] = Right[root] = R - L + 1 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; } void update(int id , int type , int L , int R , int root){ if(L == R){ Left[root] = Right[root] = type ; return ; } int mid = (L + R) >> 1 ; if(id <= mid) update(id , type , L , mid , root<<1) ; else update(id , type , mid + 1 , R ,root<<1|1) ; push_up(L , R , root) ; } int query(int id , int L , int R , int root){ if(L == R) return Left[root] ; int mid = (L + R) >> 1 ; if(id <= mid){ if(Left[root<<1] == mid - L + 1) return Left[root<<1] + Left[root<<1|1] ; else if(L + Left[root<<1] > id) return Left[root<<1] ; else if(id > mid - Right[root<<1]) return Right[root<<1] + Left[root<<1|1] ; else return query(id , L , mid , root<<1) ; } else{ if(Right[root<<1|1] == R - mid) return Right[root<<1|1] + Right[root<<1] ; else if(id > R - Right[root<<1|1]) return Right[root<<1|1] ; else if(mid + 1 + Left[root<<1|1] > id) return Right[root<<1] + Left[root<<1|1] ; else return query(id , mid+1 , R , root<<1|1) ; } } int main(){ int n , m , id ; stack<int> me ; char str[2] ; while(cin>>n>>m){ while(!me.empty()) me.pop() ; make_tree(1,n,1) ; while(m--){ scanf("%s" , str) ; if(str[0] == 'D'){ scanf("%d",&id) ; update(id , 0 , 1 , n , 1) ; me.push(id) ; } else if(str[0] == 'R'){ if(!me.empty()){ update(me.top() , 1 , 1 , n , 1) ; me.pop() ; } } else{ scanf("%d",&id) ; printf("%d\n",query(id,1,n,1)) ; } } } return 0 ; }
const int Max_N = 1000008 ; int color[Max_N<<2] , final_color[Max_N] ; void push_down(int root){ if(color[root]){ color[root<<1] = color[root<<1|1] = color[root] ; color[root] = 0 ; } } void make_tree(int L , int R , int root){ color[root] = 0 ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; } void update(int l , int r , int c , int L , int R , int root){ if(l <= L && R <= r){ color[root] = c ; return ; } push_down(root) ; int mid = (L + R) >> 1 ; if(l <= mid) update(l , r , c , L , mid , root<<1) ; if(r > mid) update(l , r , c , mid+1 , R , root<<1|1) ; } void query(int L , int R , int root){ if(L == R){ final_color[L] = color[root] ; return ; } push_down(root) ; int mid = (L + R) >> 1 ; query(L , mid , root<<1) ; query(mid+1 , R , root<<1|1) ; } int Ans(int N){ int ans = 0 ; int now = final_color[1] , num = 1 ; for(int i = 2 ; i <= N ; i++){ if(final_color[i] == now) num++ ; else{ if(now) ans = max(ans , num) ; now = final_color[i] ; num = 1 ; } } if(now) ans = max(ans , num) ; return ans ; } int main(){ int n , m , i , l , r; while(scanf("%d%d" , &n ,&m) != EOF){ make_tree(1 , n , 1) ; for(i = 1 ; i <= m ; i++){ scanf("%d%d" , &l , &r) ; if(l > r) swap(l , r) ; update(l , r , i , 1 , n , 1) ; } query(1 , n , 1) ; printf("%d\n" , Ans(n)) ; } return 0 ; }
(1)"1 x y c",代表 把区间 [x,y] 上的值全部加c
(2)"2 x y c",代表 把区间 [x,y] 上的值全部乘以c
(3)"3 x y c" 代表 把区间 [x,y]上的值全部赋值为c
(4)"4 x y p" 代表 求区间 [x,y] 上值的p次方和1<=p<=3
const int Max_N = 100008 ; const int Mod = 10007 ; void ADD(int &x , int y){ x = ( x + y ) % Mod ; } struct Node{ int L , R ; int sum[4]; int mult , add ; int Len(){ return R - L + 1 ; } int Mid(){ return (L + R) >> 1 ; } void Init(int l , int r){ L = l ; R = r ; sum[1] = sum[2] = sum[3] = 0 ; mult = 1 ; add = 0 ; } void DoMult(int x){ sum[1] = sum[1] * x % Mod ; sum[2] = sum[2] * x % Mod * x % Mod ; sum[3] = sum[3] * x % Mod * x % Mod * x % Mod ; mult = mult * x % Mod ; add = add * x % Mod ; } void DoAdd(int x){ ADD(sum[3] , 3 * x * sum[2] % Mod) ; ADD(sum[3] , 3 * x * x % Mod * sum[1]) ; ADD(sum[3] , x * x % Mod * x % Mod * Len()) ; ADD(sum[2] , sum[1] * 2 * x % Mod) ; ADD(sum[2] , x * x % Mod * Len() % Mod) ; ADD(sum[1] , x * Len() % Mod) ; ADD(add , x) ; } } ; Node seg[Max_N << 2] ; void push_up(int root){ for(int i = 1 ; i <= 3 ; i++){ seg[root].sum[i] = (seg[root<<1].sum[i] + seg[root<<1|1].sum[i]) % Mod ; } } void push_down(int root){ seg[root<<1].DoMult(seg[root].mult) ; seg[root<<1].DoAdd(seg[root].add) ; seg[root<<1|1].DoMult(seg[root].mult) ; seg[root<<1|1].DoAdd(seg[root].add) ; seg[root].mult = 1 ; seg[root].add = 0 ; } void make_tree(int root , int L , int R){ seg[root].Init(L , R) ; if(L == R) return ; int mid = (L + R) >> 1 ; make_tree(root<<1 , L , mid) ; make_tree(root<<1|1 , mid+1 , R) ; push_up(root) ; } void update(int root , int L , int R , int _mult , int _add){ if(seg[root].L == L && seg[root].R == R){ seg[root].DoMult(_mult) ; seg[root].DoAdd(_add) ; return ; } push_down(root) ; int mid = seg[root].Mid() ; if(R <= mid) update(root<<1 , L , R , _mult , _add) ; else if(L > mid) update(root<<1|1 , L , R , _mult , _add) ; else{ update(root<<1 , L , mid , _mult , _add) ; update(root<<1|1 , mid+1 , R , _mult , _add) ; } push_up(root) ; } int query(int root , int L , int R , int type){ if(seg[root].L == L && seg[root].R == R) return seg[root].sum[type] ; push_down(root) ; int mid = seg[root].Mid() ; int ans = 0 ; if(R <= mid) return query(root<<1 , L , R , type) ; else if(L > mid) return query(root<<1|1 , L , R , type) ; else return (query(root<<1 , L , mid , type) + query(root<<1|1 , mid+1 , R , type) ) % Mod; } int main(){ int n , m , k , l , r , c; while(scanf("%d%d" ,&n ,&m)){ if(n == 0 && m == 0) break ; make_tree(1 , 1 , n) ; while(m--){ scanf("%d%d%d%d" ,&k , &l , &r , &c) ; if(k == 1) update(1 , l , r , 1 , c) ; else if(k == 2) update(1 , l , r , c , 0) ; else if(k == 3) update(1 , l , r , 0 , c) ; else printf("%d\n" ,query(1 , l , r , c)) ; } } return 0 ; }
const int Max_N = 100008 ; int sum[Max_N<<2] ; LL ans[Max_N<<2][5] ; int x[Max_N] , query[Max_N] ; char opt[Max_N][8] ; void up(int t){ for(int i = 0 ; i < 5 ; i++) ans[t][i] = ans[t<<1][i] + ans[t<<1|1][(i-sum[t<<1]%5 + 5)%5] ; } void make(int L , int R , int t){ memset(ans[t] , 0 , sizeof(ans[t])) ; sum[t] = 0 ; if(L == R) return ; int M = (L + R) >> 1 ; make(L , M , t<<1) ; make(M+1 , R ,t<<1|1) ; } void update(int i , int g , int L , int R , int t){ sum[t] += (g==0? -1 : 1) ; if(L == R){ ans[t][0] = (LL)(g*x[i]) ; return ; } int M = (L + R) >> 1 ; if(i <= M) update(i , g , L , M , t<<1) ; else update(i , g , M+1 ,R , t<<1|1) ; up(t) ; } int main(){ int i , n , t , pos ; while(scanf("%d" ,&n) != EOF){ t = 0 ; for(i = 1 ; i <= n ; i++){ scanf("%s" , opt[i]) ; if(opt[i][0] == 'a' || opt[i][0] == 'd'){ scanf("%d" ,&query[i]) ; x[t++] = query[i] ; } } sort(x , x+t) ; t = unique(x , x + t) - x ; make(0 , t-1 , 1) ; for(i = 1 ; i <= n ; i++){ if(opt[i][0] == 's') printf("%I64d\n" ,ans[1][2]) ; else{ pos = lower_bound(x , x+t , query[i]) - x ; if(opt[i][0] == 'a') update(pos , 1 , 0 , t-1 , 1) ; else update(pos , 0 , 0 , t-1 , 1) ; } } } return 0 ; }
const int maxn = 100008 ; int lmax[maxn<<2] , rmax[maxn<<2] , amax[maxn<<2] ; int x[maxn] ; void up(int t , int L , int R){ lmax[t] = lmax[t<<1] ; rmax[t] = rmax[t<<1|1] ; amax[t] = max(amax[t<<1] , amax[t<<1|1]) ; int M = (L + R) >> 1 ; if(x[M] < x[M+1]){ if(lmax[t] == M - L + 1) lmax[t] += lmax[t<<1|1] ; if(rmax[t] == R - M) rmax[t] += rmax[t<<1] ; amax[t] = max(amax[t] , rmax[t<<1] + lmax[t<<1|1]) ; } } void make(int L , int R , int t){ if(L == R){ lmax[t] = rmax[t] = amax[t] = 1 ; return ; } int M = (L + R) >> 1 ; make(L , M , t<<1) ; make(M+1, R , t<<1|1) ; up(t , L , R) ; } void update(int i , int L , int R , int t){ if(L == R) return ; int M = (L + R) >> 1 ; if(i <= M) update(i , L , M , t<<1) ; else update(i , M+1 , R , t<<1|1) ; up(t , L , R) ; } int ask(int l , int r , int L , int R , int t){ if(l <= L && R <= r) return amax[t] ; int M = (L + R) >> 1 ; if(r <= M) return ask(l , r , L , M , t<<1) ; if(l > M) return ask(l , r , M+1 , R , t<<1|1) ; int s = max( ask(l , r , L , M , t<<1) , ask(l , r , M+1 , R , t<<1|1) ) ; if(x[M] < x[M+1]) s = max(s , min(rmax[t<<1] , M-l+1) + min(lmax[t<<1|1] , r-M) ) ; return s ; } int main(){ int i , n , t , m , id , a , b ; char s[2] ; cin>>t ; while(t--){ scanf("%d%d" ,&n ,&m) ; for(i = 1 ; i <= n ; i++) scanf("%d" ,&x[i]) ; make(1 , n , 1) ; id = 0 ; while(m--){ scanf("%s%d%d" ,s , &a , &b) ; if(s[0] == 'U'){ x[++a] = b ; update(a , 1 , n , 1) ; } else{ a++ , b++ ; printf("%d\n" , ask(a , b , 1 , n , 1)) ; } } } return 0 ; }
const int maxn = 100008 ; int lmax[maxn<<2] , rmax[maxn<<2] , amax[maxn<<2] ; int x[maxn] , add[maxn<<2] , lx[maxn<<2] , rx[maxn<<2] ; void up(int t , int L , int R){ lx[t] = lx[t<<1] ; rx[t] = rx[t<<1|1] ; lmax[t] = lmax[t<<1] ; rmax[t] = rmax[t<<1|1] ; amax[t] = max(amax[t<<1] , amax[t<<1|1]) ; int M = (L + R) >> 1 ; if(rx[t<<1] < lx[t<<1|1]){ if(lmax[t] == M - L + 1) lmax[t] += lmax[t<<1|1] ; if(rmax[t] == R - M) rmax[t] += rmax[t<<1] ; amax[t] = max(amax[t] , rmax[t<<1] + lmax[t<<1|1]) ; } } void down(int t){ if(add[t]){ add[t<<1] += add[t] ; add[t<<1|1] += add[t] ; lx[t<<1] += add[t] ; rx[t<<1] += add[t] ; lx[t<<1|1] += add[t] ; rx[t<<1|1] += add[t] ; add[t] = 0 ; } } void make(int L , int R , int t){ add[t] = 0 ; if(L == R){ lmax[t] = rmax[t] = amax[t] = 1 ; lx[t] = x[L] ; rx[t] = x[L] ; return ; } int M = (L + R) >> 1 ; make(L , M , t<<1) ; make(M+1, R , t<<1|1) ; up(t , L , R) ; } void update(int l , int r , int a , int L , int R , int t){ if(l <= L && R <= r){ add[t] += a ; lx[t] += a ; rx[t] += a ; return ; } down(t) ; int M = (L + R) >> 1 ; if(l <= M) update(l ,r , a , L , M , t<<1) ; if(r > M) update(l ,r , a , M+1 , R , t<<1|1) ; up(t , L , R) ; } int ask(int l , int r , int L , int R , int t){ if(l <= L && R <= r) return amax[t] ; int M = (L + R) >> 1 ; if(r <= M) return ask(l , r , L , M , t<<1) ; if(l > M) return ask(l , r , M+1 , R , t<<1|1) ; int s = max( ask(l , r , L , M , t<<1) , ask(l , r , M+1 , R , t<<1|1) ) ; if(rx[t<<1] < lx[t<<1|1]) s = max(s , min(rmax[t<<1] , M-l+1) + min(lmax[t<<1|1] , r-M) ) ; return s ; } int main(){ int i , n , t , m , id , a , b , c , T = 1 ; char s[2] ; cin>>t ; while(t--){ scanf("%d%d" ,&n ,&m) ; printf("Case #%d:\n" ,T++) ; for(i = 1 ; i <= n ; i++) scanf("%d" ,&x[i]) ; make(1 , n , 1) ; id = 0 ; while(m--){ scanf("%s" ,s) ; if(s[0] == 'a'){ scanf("%d%d%d" ,&a ,&b ,&c) ; update(a , b ,c , 1 ,n , 1) ; } else{ scanf("%d%d" ,&a ,&b) ; printf("%d\n" , ask(a , b , 1 , n , 1)) ; } } } return 0 ; }
const int maxn = 100008 ; int preb[maxn<<2] , sufb[maxn<<2] , mxb[maxn<<2] ; int prew[maxn<<2] , sufw[maxn<<2] , mxw[maxn<<2] ; int color[maxn<<2] ; void up(int t , int L , int R){ int M = (L + R) >> 1 ; preb[t] = preb[t<<1] ; sufb[t] = sufb[t<<1|1] ; if(preb[t] == M-L+1) preb[t] += preb[t<<1|1] ; if(sufb[t] == R-M) sufb[t] += sufb[t<<1] ; prew[t] = prew[t<<1] ; sufw[t] = sufw[t<<1|1] ; if(prew[t] == M-L+1) prew[t] += prew[t<<1|1] ; if(sufw[t] == R-M) sufw[t] += sufw[t<<1] ; mxb[t] = max(mxb[t<<1] , mxb[t<<1|1]) ; mxb[t] = max(mxb[t] , sufb[t<<1] + preb[t<<1|1]) ; mxw[t] = max(mxw[t<<1] , mxw[t<<1|1]) ; mxw[t] = max(mxw[t] , sufw[t<<1] + prew[t<<1|1]) ; } void change(int t){ swap(preb[t] , prew[t]) ; swap(sufb[t] , sufw[t]) ; swap(mxb[t] , mxw[t]) ; } void down(int t){ if(color[t]){ change(t<<1) ; change(t<<1|1) ; color[t<<1] ^= 1 ; color[t<<1|1] ^= 1 ; color[t] = 0 ; } } void make(int L , int R , int t){ color[t] = 0 ; if(L == R){ int x ; scanf("%d" ,&x) ; if(x == 1){ preb[t] = sufb[t] = mxb[t] = 1 ; prew[t] = sufw[t] = mxw[t] = 0 ; } else{ preb[t] = sufb[t] = mxb[t] = 0 ; prew[t] = sufw[t] = mxw[t] = 1 ; } return ; } int M = (L + R) >> 1 ; make(L , M , t<<1) ; make(M+1 , R , t<<1|1) ; up(t , L , R) ; } void update(int l , int r , int L , int R , int t){ if(l <= L && R <= r){ change(t) ; color[t] ^= 1 ; return ; } down(t) ; int M = (L + R) >> 1 ; if(l <= M) update(l , r , L , M , t<<1) ; if(r > M) update(l , r , M+1 , R , t<<1|1) ; up(t , L , R) ; } int ask(int l , int r , int L , int R , int t){ if(l <= L && R <= r) return mxb[t] ; down(t) ; int M = (L + R) >> 1 ; if(r <= M) return ask(l , r , L , M , t<<1) ; if(l > M) return ask(l , r , M+1 , R , t<<1|1) ; int s = max( ask(l , r , L , M , t<<1) , ask(l , r , M+1 , R , t<<1|1) ) ; s = max(s , min(sufb[t<<1] , M-l+1) + min(preb[t<<1|1] , r-M) ) ; return s ; } int main(){ int n , i , m , k , a , b ; while(scanf("%d" ,&n) != EOF){ make(1 , n , 1) ; scanf("%d" ,&m) ; while(m--){ scanf("%d%d%d" ,&k , &a ,&b) ; if(k) update(a , b , 1 , n , 1) ; else printf("%d\n" , ask(a , b , 1 , n , 1)) ; } } return 0 ; }
const int maxn = 10008 ; int color[maxn<<4] ; set<int> st ; void down(int t){ if(color[t] != -1){ color[t<<1] = color[t<<1|1] = color[t] ; color[t] = -1 ; } } void update(int l , int r , int c , int L , int R , int t){ if(l <= L && R <= r){ color[t] = c ; return ; } down(t) ; int M = (L + R) >> 1 ; if(l <= M) update(l , r , c , L , M , t<<1) ; if(r > M) update(l , r , c , M+1, R , t<<1|1) ; } int sum ; void query(int L , int R , int t){ if(color[t] != -1){ if(st.find(color[t]) == st.end()){ sum++ ; st.insert(color[t]) ; } return ; } if(L == R) return ; int M = (L + R) >> 1 ; query(L , M , t<<1) ; query(M+1 , R , t<<1|1) ; } int x[maxn<<2] , li[maxn] , ri[maxn] ; int main(){ int t , n , m , i , k , l , r ; cin>>t ; while(t--){ scanf("%d" ,&n) ; memset(color , -1 , sizeof(color)) ; k = 0 ; for(i = 1 ; i <= n ; i++){ scanf("%d%d" ,&li[i] , &ri[i]) ; x[k++] = li[i] ; x[k++] = ri[i] ; } sort(x , x+k) ; k = unique(x , x+k) - x ; for(i = k-1 ; i > 0 ; i--){ if(x[i] != x[i-1] + 1) x[k++] = x[i-1] + 1 ; } sort(x , x+k) ; for(i = 1 ; i <= n ; i++){ l = lower_bound(x , x+k , li[i]) - x ; r = lower_bound(x , x+k , ri[i]) - x ; update(l , r , i , 0 , k-1 , 1) ; } st.clear() ; sum = 0 ; query(0 , k-1 , 1) ; printf("%d\n" , sum) ; } return 0 ; }
const int maxn = 2008 ; int color[maxn<<4] ; void down(int t){ if(color[t] != -1){ color[t<<1] = color[t<<1|1] = color[t] ; color[t] = -1 ; } } void make(int L , int R , int t){ color[t] = -1 ; if(L == R){ color[t] = 0 ; return ; } int M = (L + R) >> 1 ; make(L , M , t<<1) ; make(M+1 , R , t<<1|1) ; } void update(int l , int r , int c , int L , int R , int t){ if(l <= L && R <= r){ color[t] = c ; return ; } down(t) ; int M = (L + R) >> 1 ; if(l <= M) update(l , r , c , L , M , t<<1) ; if(r > M) update(l , r , c , M+1, R , t<<1|1) ; } int vis[maxn<<2] ; void query(int L , int R , int t){ if(color[t] == 1){ for(int i = L ; i <= R ; i++) vis[i] = 1 ; return ; } if(L == R) return ; if(color[t] == -1){ int M = (L + R) >> 1 ; query(L , M , t<<1) ; query(M+1 , R , t<<1|1) ; } } int x[maxn<<2] , li[maxn] , ri[maxn] , co[maxn]; int main(){ int n , i ,j , k , l , r , st , ed ; char s[2] ;; while(cin>>n){ k = 0 ; for(i = 1 ; i <= n ; i++){ scanf("%d%d%s" ,&li[i] , &ri[i] , s) ; x[k++] = li[i] ; x[k++] = ri[i] ; if(s[0] == 'w') co[i] = 1 ; else co[i] = 0 ; } sort(x , x+k) ; k = unique(x , x+k) - x ; for(i = k-1 ; i > 0 ; i--){ if(x[i] != x[i-1] + 1) x[k++] = x[i-1] + 1 ; } sort(x , x+k) ; make(0 , k-1 , 1) ; for(i = 1 ; i <= n ; i++){ l = lower_bound(x , x+k , li[i]) - x ; r = lower_bound(x , x+k , ri[i]) - x ; update(l , r , co[i] , 0 , k-1 , 1) ; } memset(vis , 0 , sizeof(vis)) ; query(0 , k-1 , 1) ; st = -1 ; ed = -2 ; x[k] = x[k-1] + 1 ; for(i = 0 ; i < k ; i++){ if(vis[i]){ for(j = i ; j < k && vis[j] ; j++) ; j-- ; if(ed - st < x[j+1]-1 - x[i]){ st = x[i] ; ed = x[j+1] - 1 ; } i = j ; } } if(st == -1) puts("Oh, my god") ; else printf("%d %d\n" , st , ed) ; } return 0 ; }
先 dfs 将树转化成一个序列(求出每个结点的先序遍历值,以及它的所有子节点中的最大先序遍历值,以这两个值作为该结点在序列上的区间左右端点),然后用线段树维护,区间修改/区间查询,非常经典了
const int maxn = 100008 ; vector<int> g[maxn] ; int lock , sd[maxn] , td[maxn] ; void dfs(int u){ sd[u] = ++lock ; for(int i = 0 ; i < g[u].size() ; i++){ dfs(g[u][i]) ; } td[u] = lock ; } int sum[maxn<<2] , color[maxn<<2] ; void down(int t , int L , int R){ if(color[t]){ color[t<<1] ^= 1 ; color[t<<1|1] ^= 1 ; color[t] = 0 ; int M = (L + R) >> 1 ; sum[t<<1] = (M-L+1) - sum[t<<1] ; sum[t<<1|1] = (R-M) - sum[t<<1|1] ; } } void up(int t){ sum[t] = sum[t<<1] + sum[t<<1|1] ; } void update(int l , int r , int L , int R , int t){ if(l <= L && R <= r){ sum[t] = (R-L+1) - sum[t] ; color[t] ^= 1 ; return ; } down(t , L , R) ; int M = (L + R) >> 1 ; if(l <= M) update(l , r , L , M , t<<1) ; if(r > M) update(l , r , M+1 , R , t<<1|1) ; up(t) ; } int ask(int l , int r , int L , int R , int t){ if(l <= L && R <= r) return sum[t] ; down(t , L , R) ; int s = 0 , M = (L + R) >> 1 ; if(l <= M) s += ask(l , r , L , M , t<<1) ; if(r > M) s += ask(l , r , M+1 , R , t<<1|1) ; return s ; } int main(){ int n , m , i , x ; char s[2] ; while(cin>>n>>m){ for(i = 1 ; i <= n ; i++) g[i].clear() ; for(i = 2 ; i <= n ; i++){ scanf("%d" ,&x) ; g[x].push_back(i) ; } lock = 0 ; dfs(1) ; memset(sum , 0 , sizeof(sum)) ; memset(color , 0 , sizeof(color)) ; while(m--){ scanf("%s%d" ,s ,&i) ; if(s[0] == 'o') update(sd[i],td[i],1,n,1) ; else printf("%d\n" , ask(sd[i],td[i],1,n,1)) ; } puts("") ; } return 0 ; }