http://vjudge.net/problem/viewProblem.action?id=21557
题目大意:
每进行一次颜色改变都可以把一段区间内的黑石头变成白石头,白石头变成黑石头,最后问区间内黑石头连续的最大长度
这里我们可以用rev[]作为lazy标记,每次进行改变,rev[]^1
因为有黑白两种石头,我们求连续区间,需要维护黑,白两种石头的左侧最多,右侧最多和全部最多,所以我们这里可以用一个二维数组进行描述
每次做出改变,只要将黑白石头的值进行交换即可就方便了很多
对于最后访问的时候做的区间合并。。。。我确实有点拙计了,最后是学长帮忙改正的。。。。
还是有点只会套模板的嫌疑Orz,关键模板的代码是不考虑处在两个不同的区间进行合并的情况的,所以最后在所有 单个区间的情况判断完后,我们
要把左子树的右侧和右子树的左侧合并到一起,因为可能会超过访问范围,所以这里用的是:
ans = max(ans,min(mid-s+1,rc[ls][1])+min(t-mid,lc[rs][1]));
在内部取个最小值。
在此将自己拙计的query函数和正确的query函数进行一下对比:
/* void query(int cur ,int x,int y,int s,int t,int &ans) { int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; if(x>=s&&y<=t){ ans+=mc[cur][1]; return; } push_down(cur,x,y); if(mid>=s) query(L,s,t,ans); if(mid+1<=t) query(R,s,t,ans); }*/ int query(int cur,int x,int y,int s,int t){ int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; if(x>=s&&y<=t){ return mc[cur][1]; } push_down(cur,x,y); int ans = 0; if(mid>=s) ans = max(ans,query(L,s,t)); if(mid+1<=t) ans = max(ans,query(R,s,t)); ans = max(ans,min(mid-s+1,rc[ls][1])+min(t-mid,lc[rs][1])); return ans; }
总代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 100010 6 #define L ls,x,mid 7 #define R rs,mid+1,y 8 int color[N],rev[N<<2],lc[N<<2][2],rc[N<<2][2],mc[N<<2][2]; 9 void push_up(int cur,int x,int y) 10 { 11 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 12 for(int i=0;i<2;i++){ 13 lc[cur][i]=lc[ls][i],rc[cur][i]=rc[rs][i]; 14 mc[cur][i]=max(mc[ls][i],mc[rs][i]); 15 mc[cur][i]=max(mc[cur][i],rc[ls][i]+lc[rs][i]); 16 if(lc[ls][i]==mid-x+1) lc[cur][i]=lc[ls][i]+lc[rs][i]; 17 if(rc[rs][i]==y-mid) rc[cur][i]=rc[rs][i]+rc[ls][i]; 18 } 19 } 20 void push_down(int cur,int x,int y) 21 { 22 int ls=cur<<1,rs=cur<<1|1; 23 if(rev[cur]){ 24 rev[ls]^=1,rev[rs]^=1; 25 26 swap(lc[ls][0],lc[ls][1]); 27 swap(lc[rs][0],lc[rs][1]); 28 29 swap(rc[ls][0],rc[ls][1]); 30 swap(rc[rs][0],rc[rs][1]); 31 32 swap(mc[ls][0],mc[ls][1]); 33 swap(mc[rs][0],mc[rs][1]); 34 35 rev[cur]=0; 36 } 37 } 38 void build(int cur,int x,int y) 39 { 40 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 41 rev[cur]=0; 42 if(x==y){ 43 lc[cur][0]=rc[cur][0]=mc[cur][0]=color[x]^1; 44 lc[cur][1]=rc[cur][1]=mc[cur][1]=color[x]; 45 return; 46 } 47 build(L); 48 build(R); 49 push_up(cur,x,y); 50 } 51 void update(int cur,int x,int y,int s,int t) 52 { 53 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 54 if(x>=s&&y<=t){ 55 swap(lc[cur][0],lc[cur][1]); 56 swap(rc[cur][0],rc[cur][1]); 57 swap(mc[cur][0],mc[cur][1]); 58 rev[cur]^=1; 59 return; 60 } 61 push_down(cur,x,y); 62 if(mid>=s) update(L,s,t); 63 if(mid+1<=t) update(R,s,t); 64 push_up(cur,x,y); 65 } 66 /* 67 void query(int cur ,int x,int y,int s,int t,int &ans) 68 { 69 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 70 if(x>=s&&y<=t){ 71 ans+=mc[cur][1]; 72 return; 73 } 74 push_down(cur,x,y); 75 if(mid>=s) query(L,s,t,ans); 76 if(mid+1<=t) query(R,s,t,ans); 77 }*/ 78 79 int query(int cur,int x,int y,int s,int t){ 80 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 81 if(x>=s&&y<=t){ 82 return mc[cur][1]; 83 } 84 push_down(cur,x,y); 85 int ans = 0; 86 if(mid>=s) ans = max(ans,query(L,s,t)); 87 if(mid+1<=t) ans = max(ans,query(R,s,t)); 88 ans = max(ans,min(mid-s+1,rc[ls][1])+min(t-mid,lc[rs][1])); 89 return ans; 90 } 91 int main() 92 { 93 int n,m,op,a,b; 94 while(scanf("%d",&n)!=EOF){ 95 for(int i=1;i<=n;i++) scanf("%d",&color[i]); 96 build(1,1,n); 97 scanf("%d",&m); 98 for(int i=0;i<m;i++){ 99 scanf("%d%d%d",&op,&a,&b); 100 if(op) update(1,1,n,a,b); 101 else{ 102 //int ans=0; 103 //query(1,1,n,a,b,ans); 104 printf("%d\n",query(1,1,n,a,b)); 105 } 106 } 107 } 108 return 0; 109 }
HDU 3911 区间合并求最大长度的问题,布布扣,bubuko.com
原文:http://www.cnblogs.com/CSU3901130321/p/3898581.html