这里涉及多标记下推问题。
有区间 改1 改 0 和 反转10 三种操作
那末可以用一个col 标记数组来维护,0(或1)代表区间改0(或1),2代表区间反转,
由于标记2比较特殊下推时候,要特别注意,见upd_one_seg函数。
还有线段树中下推标记的关键动作。
下推标记或对分解的logn个区间加标记时原区间都可能有标记。
标记推到最底层不需在下推,(因为标记的意思为当前区间已经被更新,并且子区间未更新)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cctype>
#include <deque>
using namespace std;
typedef long long LL;
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep1(i,n) for(int (i)=1;(i)<=(n);(i)++)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 151111;
const int lim = 150000;
int col[maxn<<2];
void upd_one_seg(int rt,int v){
if(v == 2){
if(col[rt]==-1) col[rt] = 2;
else if(col[rt] == 2) col[rt] = -1;
else { col[rt]^=1; }
}
else col[rt] = v;
}
void push_down(int rt){
if(col[rt]!=-1){
upd_one_seg(rt<<1,col[rt]);
upd_one_seg(rt<<1|1,col[rt]);
col[rt] = -1;
}
}
void build(int l,int r,int rt){
col[rt] = -1;
if(l==r) return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int l,int r,int rt,int L,int R,int v){
if(L<=l&&r<=R){
upd_one_seg(rt,v);
return;
}
push_down(rt);
int m=(l+r)>>1;
if(L<=m) update(lson,L,R,v);
if(R>m) update(rson,L,R,v);
}
int query(int l,int r,int rt,int p){
if(l == r){
return col[rt];
}
push_down(rt);
int m=(l+r)>>1;
if(p<=m) return query(lson,p);
else return query(rson,p);
}
char cmd[5],str[100];
void get_num(int& x,int& y){
x=0; y=0;
int l=0,r=0,cnt=0;
int len = strlen(str);
for(int i=0;i<len;i++){
if(!i) if(str[i]=='(') l++;
if(i==len-1) if(str[i]==')') r--;
if(isdigit(str[i])){
cnt++;
int j=0,num=0;
for(j=i;j<len;j++){
if(!isdigit(str[j])) break;
num=num*10+str[j]-'0';
}
if(cnt == 1) x = num*2;
else y = num*2;
i = j-1;
}
}
x+=l; y+=r;
if(x>y) x=14990,y=14990;
}
int get(int i){
int v = query(0,lim,1,i);
if(v==-1) v = 0;
if(v==2) v = 1;
return v;
}
void show();
int main()
{
build(0,lim,1);
while(scanf("%s %s",cmd,str)!=EOF){
int x,y;
get_num(x,y);
if(cmd[0]=='U'){
update(0,lim,1,x,y,1);
}
else if(cmd[0]=='I'){
if(x-1>=0) update(0,lim,1,0,x-1,0);
update(0,lim,1,y+1,lim,0);
}
else if(cmd[0]=='D'){
update(0,lim,1,x,y,0);
}
else if(cmd[0]=='C'){
if(x-1>=0) update(0,lim,1,0,x-1,0);
update(0,lim,1,y+1,lim,0);
update(0,lim,1,x,y,2);
}
else{
update(0,lim,1,x,y,2);
}
}
show();
return 0;
}
void show(){
int cnt = 0;
int Lim = 140000;
for(int i=0;i<Lim;i++){
if(get(i)){
if(cnt) printf(" ");
if(i&1) printf("(");
else printf("[");
printf("%d,",i/2);
cnt++;
int j=i;
for(;j<Lim;j++){
if(!get(j)) break;
}
i = j-1;
printf("%d",(i+1)/2);
if(i&1) printf(")");
else printf("]");
}
}
if(cnt == 0) printf("empty set");
printf("\n");
}
本文探讨了处理多标记下推问题时的优化策略,包括区间修改、反转操作及线段树的应用。通过实现一个col标记数组来高效管理不同类型的标记,确保下推过程的正确性和性能优化。

被折叠的 条评论
为什么被折叠?



