2019.7.13 义乌模拟赛 T4 sequence

我们考虑对询问差分,设\(f(l1,r1,l2,r2)\)为左端点在\([l1,r1]\)中,右端点在\([l2,r2]\)中的答案。
那么一个询问就变成\(f(1,r,1,r)-f(1,l-1,1,l-1)-f(1,l-1,l,r)\)
前面那个十分平凡,我们考虑后面那个。
将询问离线,然后就变成每次加入一个点并更新,求答案的东西。
我们预处理出每个点最近的同色点\(las_i\),那么\([las_i+1,i]\)区间内的点答案奇偶性都会变化。
然后还要每次将一个辅助数组\(B\)加上每一位对应的奇偶性。
这个东西懒标记随便维护。再维护一个区间反转后的tag即可。
时间复杂度\(O(nlogn)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 500000
#define M 500000
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,x,y,A[N+5],tot,pus,las[N+5],F[N+5<<2],Sum[N+5<<2];ll Ans[N+5],H[N+5];
struct ques{int l,r,flag,id;}tmp;vector<ques> Q[N+5];
I void push(int l,int r,int now){F[now]^=1;Sum[now]=r-l+1-Sum[now];}
I void pushF(int l,int r,int now){if(!F[now]) return;int m=l+r>>1;push(l,m,now<<1);push(m+1,r,now<<1|1);F[now]=0;}
I void Up(int now){Sum[now]=Sum[now<<1]+Sum[now<<1|1];}
I void get(int x,int y,int l=1,int r=n,int now=1){
	if(x<=l&&r<=y) return (void)(F[now]^=1,Sum[now]=r-l+1-Sum[now]);pushF(l,r,now);int m=l+r>>1;
	x<=m&&(get(x,y,l,m,now<<1),0);y>m&&(get(x,y,m+1,r,now<<1|1),0);Up(now);
}
I int find(int x,int y,int l=1,int r=n,int now=1){
	if(x<=l&&r<=y) return Sum[now];int m=l+r>>1,ans=0;pushF(l,r,now);x<=m&&(ans+=find(x,y,l,m,now<<1));y>m&&(ans+=find(x,y,m+1,r,now<<1|1));return ans;
}
struct TrieTree{
	ll Ans[N+5<<2],Sum[N+5<<2],F[N+5<<2],H1[N+5<<2],H2[N+5<<2];
	I void Up(int now){Sum[now]=Sum[now<<1]+Sum[now<<1|1];Ans[now]=Ans[now<<1]+Ans[now<<1|1];}
	I void pushF(int now,int siz){swap(H1[now],H2[now]);F[now]^=1;Sum[now]=siz-Sum[now];}
	I void pushf(int l,int r,int now){int m=l+r>>1;F[now]&&(pushF(now<<1,m-l+1),pushF(now<<1|1,r-m),F[now]=0);}
	I void pushH1(int l,int r,int now,int w){H1[now]+=w;Ans[now]+=Sum[now]*w;}
	I void pushH2(int l,int r,int now,int w){H2[now]+=w;Ans[now]+=(r-l+1-Sum[now])*w;}
	I void pushh(int l,int r,int now){int m=l+r>>1;H1[now]&&(pushH1(l,m,now<<1,H1[now]),pushH1(m+1,r,now<<1|1,H1[now]),H1[now]=0);H2[now]&&(pushH2(l,m,now<<1,H2[now]),pushH2(m+1,r,now<<1|1,H2[now]),H2[now]=0);}
	I void getF(int x,int y,int l=1,int r=n,int now=1){
		if(x<=l&&r<=y) return pushF(now,r-l+1);int m=l+r>>1;pushf(l,r,now);pushh(l,r,now);
		x<=m&&(getF(x,y,l,m,now<<1),0);y>m&&(getF(x,y,m+1,r,now<<1|1),0);Up(now);
	}
	I void getH(int x,int y,int l=1,int r=n,int now=1){
		if(x<=l&&r<=y) return pushH1(l,r,now,1);int m=l+r>>1;pushf(l,r,now);pushh(l,r,now);
		x<=m&&(getH(x,y,l,m,now<<1),0);y>m&&(getH(x,y,m+1,r,now<<1|1),0);Up(now);
	}
	I ll find(int x,int y,int l=1,int r=n,int now=1){
		if(x<=l&&r<=y) return Ans[now];int m=l+r>>1;ll ans=0;pushf(l,r,now);pushh(l,r,now);
		x<=m&&(ans+=find(x,y,l,m,now<<1));y>m&&(ans+=find(x,y,m+1,r,now<<1|1));return ans;
	}
}S;
int main(){
	freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);
	re int i,j;scanf("%d",&n);for(i=1;i<=n;i++) scanf("%d",&A[i]);for(i=1;i<=n;i++) las[i]=H[A[i]],H[A[i]]=i;
	Me(H,0);for(i=1;i<=n;i++)get(las[i]+1,i),H[i]=H[i-1]+find(1,i);scanf("%d",&m);
	for(i=1;i<=m;i++)scanf("%d%d",&x,&y),Ans[i]=H[y]-H[x-1],x^1&&(Q[x-1].push_back((ques){1,x-1,1,i}),Q[y].push_back((ques){1,x-1,-1,i}),0);
	for(i=1;i<=n;i++){
		S.getF(las[i]+1,i);S.getH(1,i);for(j=0;j<Q[i].size();j++) tmp=Q[i][j],Ans[tmp.id]+=tmp.flag*S.find(tmp.l,tmp.r);
	}for(i=1;i<=m;i++) printf("%lld\n",Ans[i]);
}
上一篇:[CF407E]k-d-sequence


下一篇:Ducci Sequence题解