4 a b 输出[a, b]区间内最长的连续1串
解:
正解应该比较简单。然而我的解就有点Orz了。 每个节点信息是:
preb, prew,sufb,sufw,mxb,mxw,sumb,sumw,Xor 这么多。
其他几个就不用说了,sumb是记录这个区间有多少1,Xor是lazy标志(之前没有这个,果断wa了)。 然后就写得。。。不过还好,push_up没写错呵呵。。。
后续:
简单的解法就是只维护一个cov就行了。cov = 1/0,表示这个区间全是1或者全是0,cov = -1表示有多种值。Orz。。。。
/*
Pro: 0
Sol:
date:
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <vector>
#define maxn 100010
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m =(l + r) >> 1
#define lson l,m , rt << 1
#define rson m + 1 , r, rt << 1 | 1
using namespace std;
int preb[maxn << 2], sufb[maxn << 2], prew[maxn << 2], sufw[maxn << 2], mxb[maxn << 2], mxw[maxn << 2];
int sumb[maxn << 2],sumw[maxn << 2], Xor[maxn << 2];
int n,T,Q,tmp,op,a,b;
inline int max(int a, int b, int c){
return ( (a > b) ? ( (a > c) ? a: c) : ( (b > c) ? b : c) );
}
void push_up(int rt, int m){
sumb[rt] = sumb[ls] + sumb[rs];
sumw[rt] = sumw[ls] + sumw[rs];
preb[rt] = preb[ls];
if(preb[ls] == m - (m >> 1)) preb[rt] += preb[rs];
prew[rt] = prew[ls];
if(prew[ls] == m - (m >> 1)) prew[rt] += prew[rs];
sufb[rt] = sufb[rs];
if(sufb[rs] == (m >> 1)) sufb[rt] += sufb[ls];
sufw[rt] = sufw[rs];
if(sufw[rs] == (m >> 1)) sufw[rt] += sufw[ls];
mxb[rt] = max(mxb[ls], mxb[rs], preb[rs] + sufb[ls]);
mxw[rt] = max(mxw[ls], mxw[rs], prew[rs] + sufw[ls]);
}
void Exc(int rt){
swap(preb[rt],prew[rt]);
swap(sufb[rt],sufw[rt]);
swap(sumb[rt],sumw[rt]);
swap(mxb[rt],mxw[rt]);
}
void push_dn(int rt, int m){
if(Xor[rt]){//异或是lazy,又是必须
Xor[ls] ^= 1;
Xor[rs] ^= 1;
Exc(ls); Exc(rs);
Xor[rt] = 0;
}
if(sumb[rt] == m){
preb[ls] = sufb[ls] = mxb[ls] = sumb[ls] = m - (m >> 1);
preb[rs] = sufb[rs] = mxb[rs] = sumb[rs] = (m >> 1);
prew[ls] = sufw[ls] = mxw[ls] = sumw[ls] = 0;
prew[rs] = sufw[rs] = mxw[rs] = sumw[rs] = 0;
}else if(sumw[rt] == m){
preb[ls] = sufb[ls] = mxb[ls] = sumb[ls] = 0;
preb[rs] = sufb[rs] = mxb[rs] = sumb[rs] = 0;
prew[ls] = sufw[ls] = mxw[ls] = sumw[ls] = m - (m >> 1);
prew[rs] = sufw[rs] = mxw[rs] = sumw[rs] = (m >> 1);
}
}
void build(int l , int r, int rt){
Xor[rt] = 0;
if(l == r) {
scanf("%d",&tmp);
if(tmp){
preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = 1;
prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = 0;
}else{
preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = 0;
prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = 1;
}
return ;
} havem;
build(lson); build(rson);
push_up(rt, r - l + 1);
}
void update(int L, int R, int op, int l, int r, int rt){
if(L <= l && r <= R){
if(op == 0){
preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = 0;
prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = r - l + 1;
return ;
}else if(op == 1){
preb[rt] = sufb[rt] = mxb[rt] = sumb[rt] = r - l + 1;
prew[rt] = sufw[rt] = mxw[rt] = sumw[rt] = 0;
return;
}
Exc(rt); Xor[rt] ^= 1; return ;
}havem;
push_dn(rt, r - l + 1);
if(L <= m) update(L,R,op,lson);
if(R > m) update(L,R,op,rson);
push_up(rt,r - l + 1);
}
int query3(int L, int R, int l, int r, int rt){//3 all 1's ; 4 longest 1's
if(L <= l && r <= R){
return sumb[rt];
} havem;
push_dn(rt, r - l + 1);
int ret = 0;
if(L <= m) ret += query3(L,R,lson);
if(R > m) ret += query3(L,R,rson);
return ret;
}
int query4(int L, int R, int l, int r, int rt){//3 all 1's ; 4 longest 1's
if(L <= l && r <= R){
return mxb[rt];
} havem;
push_dn(rt, r - l + 1);
if(R <= m) return query4(L,R,lson);
if(L > m) return query4(L,R,rson);
int ret = max(query4(L,R,lson), query4(L,R,rson));
ret = max(ret, min(m - L + 1, sufb[ls]) + min(R - m, preb[rs]) );
return ret;
}
int main(){
scanf("%d",&T);
while(T --){
scanf("%d%d",&n,&Q);
build(0,n - 1,1);//
for(int i = 0; i < Q; i ++){
scanf("%d%d%d",&op,&a,&b);
if(op == 0){
update(a,b,op,0,n - 1,1);//期间全变为0
}else if(op == 1){
update(a,b,op,0,n - 1,1);//期间全变为1
}else if(op == 2){
update(a,b,op,0,n - 1,1);//期间0,1互换
}else if(op == 3){
printf("%d\n",query3(a,b,0,n - 1,1) );//all 1's in [a,b]
}else{
printf("%d\n",query4(a,b,0,n - 1,1) );//longest 1's in [a,b]
}
}
}
return 0;
}
#include <cstdio> using namespace std; #define maxn 100010 #define lson l, m , rt << 1 #define rson m + 1, r, rt << 1 | 1 #define ls rt << 1 #define rs rt << 1 | 1 #define havem int m = (l + r ) >> 1 int n,Q,a,b,T; //首先得声明,cov不是lazy标志,不然是不会出现在push_up里面的 int cov[maxn << 2],ri, max_len,cur_len; void push_up(int rt){ if(cov[ls] == cov[rs])//cov 可以为-1 cov[rt] = cov[ls]; else cov[rt] = -1; } void build(int l , int r, int rt){ if(l == r){ scanf("%d",&cov[rt]); return ; }havem; build(lson); build(rson); push_up(rt); } void push_dn(int rt){ if(cov[rt] >= 0){ cov[ls] = cov[rs] = cov[rt]; cov[rt] = -1; } } void update(int L, int R, int val, int l, int r, int rt){ if(cov[rt] == val) return ; if(L <= l && r <= R){ cov[rt] = val; return; }push_dn(rt); havem; if(L <= m) update(L,R,val,lson); if(R > m) update(L,R,val,rson); push_up(rt); } void update_xor(int L,int R, int l, int r, int rt){ if(L <= l && r <= R && cov[rt] >= 0){ cov[rt] ^= 1; return ; }push_dn(rt); havem; if(L <= m) update_xor(L,R,lson); if(R > m) update_xor(L,R,rson); push_up(rt); } int query(int L, int R, int l, int r, int rt){ if(L <= l && r <= R){ if(cov[rt] == 0){ return 0; } if(cov[rt] == 1){ return r - l + 1; } } havem; push_dn(rt); if(R <= m) return query(L , R, lson); if(L > m) return query(L,R,rson); return query(L , R , lson) + query(L,R,rson); } void queryl(int L,int R, int l, int r, int rt){ if(cov[rt] == 0) return ; if(L <= l && r <= R && cov[rt] == 1){ if(L == ri + 1) //现在这个区间如果接着上个区间 cur_len += r - l + 1; else cur_len = r - l + 1; if(cur_len > max_len) max_len = cur_len; ri = r; return ; }push_dn(rt); havem; if(R <= m) queryl(L , R, lson); else if(L > m) queryl(L,R,rson); else//这里是m和m + 1, 这里我wa了很久,这跟上面的L == ri + 1有关 queryl(L , m , lson), queryl( m + 1 ,R,rson); } int main(){ scanf("%d",&T); int op,a,b; while(T --){ scanf("%d%d",&n,&Q); build(1,n,1); while(Q --){ scanf("%d%d%d",&op,&a,&b); a ++, b ++; switch(op){ case 0 : update(a,b,0,1,n,1); break; case 1: update(a,b,1,1,n,1); break; case 2: update_xor(a,b,1,n,1); break; case 3: printf("%d\n",query(a,b,1,n,1) ); break; case 4: max_len = cur_len = 0; ri = 0; queryl(a,b,1, n, 1); printf("%d\n",max_len); } } } }