题解 english

骗分骗到70pts不会动了。。。亿小会后再来补坑吧。

首先1~4\(O(n^2)\)暴力过掉20pts,对于opt=1的点,单调栈求出每个点的延伸范围,

式子很好推,得40pts,

对于\(1>=a_i>=0\)的点opt=2显然ans=0,直接输出得10pts

代码就不放了,改完再放

update in 7.13

终于过了...调了半天发现自己没扔初值,后来疯狂Wa是数组开小了...

对于ans2建立可持久化TRIE树,对于每个l r看左右区间哪个小就对它查找,注意取膜即可。

Code



#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
	#define pf printf
	#define int long long
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	typedef long long ll;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	const int mod=1e9+7,N=1e5+100;
	int n,opt,a[N],l[N],r[N],tot,top,pre[N][22],son[N<<5][2],root[N],sum[N<<5],bin[22];ll maxn,ans1,ans2;
	struct node{int v,od;}stack[N],pp;
	inline void build(int &p,int dep){
		p=++tot;
		if(dep==20)return;
		build(son[p][0],dep+1);
		build(son[p][1],dep+1);
	}
	inline void insert(int x,int &y,int v,int dep){
		y=++tot;
		sum[y]=sum[x]+1;
		if(dep<0)return;
		int t=(v>>dep)&1;
		son[y][t^1]=son[x][t^1];
		insert(son[x][t],son[y][t],v,dep-1);
	}
	inline int query(int x,int y,int v,int pos,int val,int dep){
		if(dep<0)return 0;
		//pi(pos);pi(dep);pn();
		int t=(pos>>dep)&1;
		if(val+bin[dep]>v)return sum[son[y][t^1]]-sum[son[x][t^1]]+query(son[x][t],son[y][t],v,pos,val,dep-1);
		return query(son[x][t^1],son[y][t^1],v,pos,val+bin[dep],dep-1);
	}
	inline void check(int x,int dep){
		if(dep<-1)return;
		pf("dep: ");pi(dep);
		pf("son0: "),pi(sum[son[x][0]]),pn();
		if(sum[son[x][0]])check(son[x][0],dep-1);
		pf("dep: ");pi(dep);
		pf("son1: "),pi(sum[son[x][1]]),pn();
		if(sum[son[x][1]])check(son[x][1],dep-1);
	}
	inline short main(){
		file();
		n=read(),opt=read();
		F(i,1,n)a[i]=read();bin[0]=1;
		F(i,1,20)bin[i]=bin[i-1]<<1;
		F(i,1,n){
			l[i]=r[i]=i;pp.v=a[i];pp.od=i;
			while(top&&stack[top].v<a[i])r[stack[top].od]=i-1,l[i]=l[stack[top].od],--top;
			stack[++top]=pp;
		}while(top)r[stack[top].od]=n,top--;
		F(i,1,n)F(j,0,20)pre[i][j]=((a[i]&(1<<j))?1:0)+pre[i-1][j];
		F(i,1,n)if(l[i]!=r[i])F(j,0,19)(ans1+=(ll)((ll)(pre[i][j]-pre[l[i]-1][j])*((r[i]-i+1)-(pre[r[i]][j]-pre[i-1][j]))+(ll)(pre[r[i]][j]-pre[i-1][j])*((i-l[i]+1)-(pre[i][j]-pre[l[i]-1][j])))%mod*a[i]%mod*(1<<j)%mod)%=mod;
		if(opt==1){pi(ans1);return 0;}
		if(opt==3)pi(ans1),pn();
		build(root[0],0);
		F(i,1,n)insert(root[i-1],root[i],a[i],20);
		F(i,1,n)if(l[i]!=r[i]){if(i-l[i]<=r[i]-i)F(j,l[i],i)(ans2+=(ll)a[i]*query(root[i-1],root[r[i]],a[i],a[j],0,20)%mod)%=mod;else F(j,i,r[i])(ans2+=(ll)a[i]*query(root[l[i]-1],root[i],a[i],a[j],0,20)%mod)%=mod;}
		pi(ans2);
		return 0;
	}
}
signed main(){return EMT::main();}

posted @ 2021-07-13 18:12  letitdown  阅读(35)  评论(0编辑  收藏  举报