zoukankan      html  css  js  c++  java
  • bzoj 4722 由乃

    bzoj

    先考虑一种简单的情况,即这个区间是否有相同的数,因为值域大小为1000,那么当区间长度(>1000)时,根据鸽巢原理,一定会有两个相同的数,这时候可以直接输出Yuno

    进一步的,对于长度为(len)的区间,子集的值域为([0,v*len]),子集个数为(2^{len}),那么可以得到如果满足(2^{len}>v*len+1)的区间,一定有两个一样权值的子集(有交就把交去掉),可以解得这个界为(lenge 14).那么对于(le 13)的部分,就暴力枚举每个数在哪个集合中,或者是不在集合中,复杂度(O(3^{len})),其实可以(meet in the middle),先搜前一半,得到所有选取情况下(A)集合权值(-B)集合权值的值,然后搜另一个集合,直接查是否存在对应(A)集合权值(-B)集合权值的相反数,以及是否有那个值为0的方案,复杂度(O(3^{frac{len}{2}}))

    至于修改操作,那么每次询问这个值的时候给他修改总修改次数-以及修改次数 次,因为这个修改可以看成在有向图上走(x)步,所以可以预处理走一些步数的情况,修改时直接大力跳即可

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=1e5+10,M=1000+10;
    int rd()
    {
    	int x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    int n,q,v,to[M][M],cn[N],a[N],bt[N];
    void add(int x,int y){while(x<=n) bt[x]+=y,x+=x&(-x);}
    int gsm(int x){int an=0;while(x) an+=bt[x],x-=x&(-x);return an;}
    int bk[N],st[M<<2],tp,s2[M<<2],t2;
    void wk(int x)
    {
    	int dt=gsm(x)-cn[x];
    	cn[x]+=dt;
    	while(dt>v) a[x]=to[a[x]][v],dt-=v;
    	a[x]=to[a[x]][dt];
    }
    
    int main()
    {
    	n=rd(),q=rd(),v=rd();
    	for(int i=1;i<=n;++i) a[i]=rd();
    	for(int i=0;i<v;++i) to[i][0]=i,to[i][1]=1ll*i*i*i%v;
    	for(int j=2;j<=v;++j)
    		for(int i=0;i<v;++i)
    			to[i][j]=to[to[i][j-1]][1];
    	while(q--)
    	{
    		int op=rd(),l=rd(),r=rd();
    		if(op==2) add(l,1),add(r+1,-1);
    		else
    		{
    			if(r-l+1>=14) puts("Yuno");
    			else
    			{
    				int md=(r-l+1)/2;
    				bool ok=0;
    				st[tp=1]=50000;
    				for(int i=l;i<=l+md-1;++i)
    				{
    					wk(i);
    					int latp=tp;
    					for(int j=1;j<=latp;++j)
    					{
    						st[++tp]=st[j]+a[i]+1;
    						ok|=st[tp]==50000,++bk[st[tp]];
    						st[++tp]=st[j]-(a[i]+1);
    						ok|=st[tp]==50000,++bk[st[tp]];
    					}
    				}
    				s2[t2=1]=50000;
    				for(int i=l+md;!ok&&i<=r;++i)
    				{
    					wk(i);
    					int latp=t2;
    					for(int j=1;j<=latp;++j)
    					{
    						s2[++t2]=s2[j]+a[i]+1;
    						ok|=s2[t2]==50000||bk[100000-s2[t2]];
    						s2[++t2]=s2[j]-(a[i]+1);
    						ok|=s2[t2]==50000||bk[100000-s2[t2]];
    					}
    				}
    				puts(ok?"Yuno":"Yuki");
    				while(tp>1) bk[st[tp]]=0,--tp;
    			}
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    结对作业(测试版)
    回答自己的提问
    阅读一个程序员的生命周期有感
    阅读13到17章提出问题
    读8 9 10章提出问题
    5.2 5.3测试与封装
    5.1 四则运算单元测试j
    阅读5.5章6章7章提出疑问
    做汉堡
    阅读第1到第5章过程的疑问
  • 原文地址:https://www.cnblogs.com/smyjr/p/11600809.html
Copyright © 2011-2022 走看看