1. 程式人生 > 其它 >2019.7.13 義烏模擬賽 T4 sequence

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]);
}