bzoj 4722 由乃

时间:2019-09-27
本文章向大家介绍bzoj 4722 由乃,主要包括bzoj 4722 由乃使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

bzoj

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

进一步的,对于长度为\(len\)的区间,子集的值域为\([0,v*len]\),子集个数为\(2^{len}\),那么可以得到如果满足\(2^{len}>v*len+1\)的区间,一定有两个一样权值的子集(有交就把交去掉),可以解得这个界为\(len\ge 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;
}

原文地址:https://www.cnblogs.com/smyjr/p/11600809.html