HDU 3397 Sequence operation(线段树区间染色加区间合并)

妈的调了两天终于过了。。。我好菜啊。

题意

对长度为n的序列执行q种操作,

0:把区间内的值都置为0;

1:把区间内的值都置为1;

2:把区间内的0都置为1,区间内的1都置为0;

3:查询区间里1的个数;

4:查询区间里最长的连续为1的区间的长度;

题解

显然,线段树区间更新区间查询可解此题,具体是:

维护懒标标记set,区间里1的个数sum1,区间左端点l,区间右端点r,区间里最长的连续为1的区间的长度sub,区间里最长的连续为0的区间的长度zsub,区间里以左端点为起点的连续为1的区间的长度lsub1,区间里以左端点为起点的连续为0的区间的长度lsub0,区间里以又端点为起点的连续为1的区间的长度rsub1,区间里以右端点为起点的连续为0的区间的长度rsub0,区间里以左端点为起点的连续为1的区间的长度lsub1。把这十个给维护好就行了呀。

  1 #define dbg(x) cout<<#x<<" = "<< (x)<< endl
  2 #define IO std::ios::sync_with_stdio(0);
  3 #include 
  4 #define iter ::iterator
  5 using namespace  std;
  6 typedef long long ll;
  7 typedef pairP;
  8 #define pb push_back
  9 #define se second
 10 #define fi first
 11 #define rs o<<1|1
 12 #define ls o<<1
 13 const ll inf=0x7fffffff;
 14 const int N=1e5+10;
 15 struct node{
 16     int sum1,lsub0,lsub1,rsub0,rsub1;
 17     int l,r,sub,zsub;
 18     int set;
 19 }a[N*4];
 20 void push(int o,int l,int r){
 21     int g=r-l+1;
 22     int gl=a[ls].r-a[ls].l+1;
 23     int gr=a[rs].r-a[rs].l+1;
 24     a[o].sum1=a[ls].sum1+a[rs].sum1;
 25     a[o].lsub0=a[ls].lsub0;
 26     a[o].rsub0=a[rs].rsub0;
 27 
 28     if(a[o].lsub0==gl){
 29         a[o].lsub0+=a[rs].lsub0;
 30     }
 31     if(a[o].rsub0==gr){
 32         a[o].rsub0+=a[ls].rsub0;
 33     }
 34     a[o].lsub1=a[ls].lsub1;
 35     a[o].rsub1=a[rs].rsub1;
 36     if(a[o].lsub1==gl){
 37         a[o].lsub1+=a[rs].lsub1;
 38     }
 39     if(a[o].rsub1==gr){
 40         a[o].rsub1+=a[ls].rsub1;
 41     }
 42     a[o].sub=max(a[ls].rsub1+a[rs].lsub1,max(a[ls].sub,a[rs].sub));
 43     a[o].zsub=max(a[ls].rsub0+a[rs].lsub0,max(a[ls].zsub,a[rs].zsub));
 44 }
 45 void sw(int o,int l,int r){
 46     int g=r-l+1;
 47     a[o].set=1-a[o].set;
 48     a[o].sum1=g-a[o].sum1;
 49     swap(a[o].lsub0,a[o].lsub1);
 50     swap(a[o].rsub0,a[o].rsub1);
 51     swap(a[o].sub,a[o].zsub);
 52 }
 53 void down(int o,int l,int r){
 54     int g=r-l+1;
 55     int gl=a[ls].r-a[ls].l+1;
 56     int gr=a[rs].r-a[rs].l+1;
 57     int x=a[o].set;
 58     if(x==-1)return;
 59     if(x<2){
 60         a[ls].set=a[rs].set=x;
 61         a[ls].lsub1=a[ls].rsub1=a[ls].sum1=a[ls].sub=x?gl:0;
 62         a[rs].lsub1=a[rs].rsub1=a[rs].sum1=a[rs].sub=x?gr:0;
 63         a[ls].lsub0=a[ls].rsub0=a[ls].zsub=x?0:gl;
 64         a[rs].lsub0=a[rs].rsub0=a[rs].zsub=x?0:gr;
 65         a[o].set=-1;
 66     }
 67     else{
 68         a[o].set=-1;
 69         int m=(l+r)/2;
 70         sw(ls,l,m);
 71         sw(rs,m+1,r);
 72     }
 73 }
 74 void build(int o,int l,int r){
 75     a[o].set=-1;
 76     if(l==r){
 77         int x;
 78         scanf("%d",&x);
 79         a[o].l=a[o].r=l;
 80         a[o].sum1=a[o].lsub1=a[o].rsub1=a[o].sub=x;
 81         a[o].lsub0=a[o].rsub0=a[o].zsub=1-x;
 82         return;
 83     }
 84     int m=(l+r)/2;
 85     build(ls,l,m);
 86     build(rs,m+1,r);
 87     a[o].l=a[ls].l;
 88     a[o].r=a[rs].r;
 89     push(o,l,r);
 90 }
 91 void up(int o,int l,int r,int ql,int qr,int k){
 92     int g=r-l+1;
 93     int gl=a[ls].r-a[ls].l+1;
 94     int gr=a[rs].r-a[rs].l+1;
 95     if(l>=ql&&r<=qr){
 96         if(k<2){
 97             a[o].set=k;
 98             a[o].lsub1=a[o].rsub1=a[o].sub=a[o].sum1=k?g:0;
 99             a[o].lsub0=a[o].rsub0=a[o].zsub=k?0:g;
100         }
101         else sw(o,l,r);
102         return;
103     }
104     down(o,l,r);
105     int m=(l+r)/2;
106     if(ql<=m)up(ls,l,m,ql,qr,k);
107     if(qr>m)up(rs,m+1,r,ql,qr,k);
108     push(o,l,r);
109 }
110 int qu(int o,int l,int r,int ql,int qr,int k){
111     if(k==3){
112         if(l>=ql&&r<=qr){
113             return a[o].sum1;
114         }
115         down(o,l,r);
116         int m=(l+r)/2;
117         int res=0;
118         if(ql<=m)res+=qu(ls,l,m,ql,qr,k);
119         if(qr>m)res+=qu(rs,m+1,r,ql,qr,k);
120         return res;
121     }
122     if(l>=ql&&r<=qr){
123         return a[o].sub;
124     }
125     down(o,l,r);
126     int m=(l+r)/2;
127     int res=min(a[ls].rsub1,m-ql+1)+min(a[rs].lsub1,qr-m);
128     if(ql<=m)res=max(res,qu(ls,l,m,ql,qr,k));
129     if(qr>m)res=max(res,qu(rs,m+1,r,ql,qr,k));
130     return res;
131 }
132 int T,n,q;
133 int main(){
134     scanf("%d",&T);
135     while(T--){
136         scanf("%d%d",&n,&q);
137         build(1,1,n);
138         while(q--){
139             int k,l,r;
140             scanf("%d%d%d",&k,&l,&r);
141             l++;
142             r++;
143             if(k<=2)up(1,1,n,l,r,k);
144             else printf("%d\n",qu(1,1,n,l,r,k));
145         }
146     }
147 }  

 

你可能感兴趣的:(HDU 3397 Sequence operation(线段树区间染色加区间合并))