• SDOI2017 R2泛做


    由于各种原因,在bzoj上我day1的题一题都没过,所以这里就直接贴loj的链接好了。

    D1T1 龙与地下城

    中心极限定理。

    https://en.wikipedia.org/wiki/Central_limit_theorem

    由于某些原因这里的公式挂了...直接看维基吧...

    要算积分可以用标准库里的erf:https://en.wikipedia.org/wiki/Error_function

    对于正态分布image,值落在[-x,x]的概率为image,所以落在[0,x]的概率就是这个值的一半,这玩意儿就可以直接当做不定积分了。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 666666
    int x,y,a,b,T;
    ld f[2333333];
    void sol()
    {
        scanf("%d%d",&x,&y);
        if((ll)x*y*y<=51200000)
        {
            for(int i=0;i<=x*y;++i) f[i]=1;
            for(int i=1;i<=y;++i)
            {
                for(int j=x*y;j>=x;--j)
                    f[j]-=f[j-x];
                for(int j=0;j<=x*y;++j)
                {
                    f[j]/=x;
                    if(j) f[j]+=f[j-1];
                }
            }
            for(int i=1;i<=10;++i)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                ld ans=f[r];
                if(l) ans-=f[l-1];
                printf("%.10lf
    ",ans);
            }
        }
        else
        {
            int n=y; ld m=(x-1)/2.0,s=(x*(ld)x-1)/12;
            ld k=-n*m,b=sqrt(n*s*2);
            for(int i=1;i<=10;++i)
            {
                ld l,r;
                scanf("%lf%lf",&l,&r);
                l-=0.5,r+=0.5;
                l=(l+k)/b; r=(r+k)/b;
                printf("%.10lf
    ",(erf(r)-erf(l))/2);
            }
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T--) sol();
    }

    D1T2 苹果树

    首先如果是树上有父亲限制的01背包,可以参见http://www.cnblogs.com/zzqsblog/p/5537440.html

    现在不是01背包了,为了方便起见,一个ai>1的点我们拆成一个ai=1和一个ai比原来少1的点,把这个新点挂在ai=1的点下面进行dp。

    多重背包显然可以单调队列优化。

    现在剩的就是那个莫名其妙的k。我们枚举一条到叶子的链(注意这里我们忽略ai>1的点),那么我们的要求就是在除了这条链以外最多只能有k个点。

    我们进行一次这个背包,可以得到一个dfs序,即我们可以得到一个dfs序后缀的背包信息,那我们把每个点的儿子反过来再得到一个dfs序,把两个dfs序这两个后缀并在一起,恰好就是整棵树去掉这条链,泛化背包类似搞搞就行。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Tree vector<int> ch[SZ];
    void setf(int x,int f) {ch[f].pb(x);}
    #define esb(x,e,b) 
    (unsigned __=0,b=(__<ch[x].size())?(ch[x][__]):0;
    __<ch[x].size();++__,b=(__<ch[x].size())?(ch[x][__]):0)
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 1234567
    namespace FF
    {
    char ch,B[1<<20],*S=B,*T=B;
    #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<20,stdin),S==T)?0:*S++)
    #define isd(c) (c>='0'&&c<='9')
    int aa,bb;int F(){
        while(ch=getc(),!isd(ch)&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
        while(ch=getc(),isd(ch))aa=aa*10+ch-'0';return bb?aa:-aa;
    }
    }
    #define gi FF::F()
    int T,n,k;
    #define max(a,b) (((a)>(b))?(a):(b))
    #define cmax(a,b) (((a)<(b))?((a)=(b)):0)
    Tree
    int m1[52111111],m2[52111111];
    #define R(x,a) (x+(a)*(k+1))
    inline void pack(int*r,int v,int x) //x个重1价值v
    {
        if(!x);
        else if(x==1)
            for(int i=k;i>=1;--i)
                cmax(r[i],r[i-1]+v);
        else if(x>=k)
            for(int i=1;i<=k;++i)
                cmax(r[i],r[i-1]+v);
        else
        {
            static pii qs[SZ];
            int h=0,t=0;
            for(int j=1;j<=k;j++)
            {
                int cv=r[j]-j*v;
                while(h!=t&&qs[t-1].fi<cv) --t;
                qs[t++]=pii(cv,j);
                while(qs[h].se<j-x) ++h;
                r[j]=qs[h].fi+j*v;
            }
        }
    }
    int fa[SZ],a[SZ],v[SZ],dep[SZ],fc[SZ];
    int d1[SZ],c1=0,l1[SZ],d2[SZ],c2=0,l2[SZ],r1[SZ],r2[SZ];
    inline void dfs(int x,int*d,int&c,int*l,int*r)
    {
        d[x]=++c; r[c]=x;
        for esb(x,e,b)
            dep[b]=dep[x]+1,fc[b]=fc[x]+v[b],
            dfs(b,d,c,l,r);
        l[x]=c;
    }
    inline void work(int*d,int&c,int*l,int*p,int*r)
    {
        for(int i=c;i>=1;--i)
        {
            int x=r[i],*A=R(p,d[x]),*B=R(p,l[x]+1),*C=R(p,d[x]+1);
            for(int s=1;s<=k;s++)
                A[s]=max(B[s],C[s-1]+v[x]);
            pack(A,v[x],a[x]-1);
        }
    }
    bool good[SZ];
    void sol()
    {
        n=gi,k=gi; int N=n; c1=c2=0;
        for(int i=1;i<=n+n;++i)
            good[i]=1,ch[i].clear();
        ll tot=0;
        for(int i=1;i<=N;++i)
        {
            fa[i]=gi,a[i]=gi,v[i]=gi; tot+=a[i];
            if(fa[i]) setf(i,fa[i]),good[fa[i]]=0;
            if(a[i]>1)
            {
                ++n; setf(n,i); a[n]=a[i]-1; good[n]=0;
                v[n]=v[i]; fa[n]=i; a[i]=1;
            }
        }
        int tt=(n+2)*(k+1);
        memset(m1,0,tt*sizeof(int));
        memset(m2,0,tt*sizeof(int));
        dep[1]=1; fc[1]=v[1];
        dfs(1,d1,c1,l1,r1);
        work(d1,c1,l1,m1,r1);
        for(int i=1;i<=n;++i)
            reverse(ch[i].begin(),ch[i].end());
        dfs(1,d2,c2,l2,r2);
        work(d2,c2,l2,m2,r2);
        int ans=0;
        for(int i=1;i<=n;++i)
        {
            if(!good[i]) continue;
            int x=min(tot-dep[i],(ll)k);
            int*f=R(m1,d1[i]+1),*g=R(m2,l2[i]+1);
            for(int s=0;s<=x;++s)
                cmax(ans,fc[i]+f[s]+g[x-s]);
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        T=gi; while(T--) sol();
    }

    D1T3 切树游戏

    这里讲一下本人常数很大的做法。首先众所周知如果有一个序列A和一个序列B,A和B做异或卷积等于C,那么fwt(A)*fwt(B)(点乘)=fwt(C)。

    我们记v[i]为单点值fwt之后的数组,那么有如下的dp方程:

    $s[i]=v[i]prod_cs[c]+1$(c是i的孩子,+1是加上空子树的情况)

    最后我们要求的是$sum_{i=1}^ns[i]$。求出这玩意儿之后ifwt回去,把n个空子树扣掉就有答案了。

    考虑记$g[i]=v[i]prod_{c'}s[c']$,c'是i的轻孩子。

    这玩意儿可以支持修改,只要修改的时候跳重链就好。

    现在的问题就是要求出重链顶端的s值以及把一整条重链的s值求和。

    我们只考虑重链的话,可以发现$s[i]=s[w]g[i]+1$,w是i的重孩子,如果我们把g预处理成矩阵(每个元素都是向量),然后这玩意儿是可以矩乘的,同时也可以顺便把s求和。然后线段树维护一下就好了。注意到矩阵有一些位置是不变的可以减小常数。

    这玩意儿还是常数爆炸了,那我也没有办法,复杂度都是一样的...

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 66666
    #pragma pack(1)
    int n,m,q; Edg
    #define SZ 33333
    const int MOD=10007;
    int inv[MOD+3];
    struct num
    {
    short x; short z;
    num() {x=z=1;}
    num(int p) {(p%=MOD)?(x=p,z=0):(x=z=1);}
    inline operator int() const {return z?0:x;}
    };
    inline num operator * (num a,num b)
    {a.x=int(a.x)*b.x%MOD; a.z+=b.z; return a;}
    inline num operator / (num a,num b)
    {a.x=int(a.x)*inv[b.x]%MOD; a.z-=b.z; return a;}
    template<class T>
    struct arr
    {
    T g[129];
    arr() {for(int i=0;i<m;++i) g[i]=0;}
    void fwt()
    {
        for(int i=1;i<m;i<<=1)
        {
            for(int j=0;j<m;++j)
            {
                if(j&i) continue;
                int a=g[j],b=g[j|i];
                g[j]=(a+b)%MOD;
                g[j|i]=(a+MOD-b)%MOD; 
            }
        }
    }
    void ifwt() //only for <short>
    {
        fwt();
        for(int i=0;i<m;++i)
            g[i]=g[i]*(int)inv[m]%MOD;
    }
    template<class T1> 
    operator arr<T1> ()
    {
        arr<T1> r;
        for(int i=0;i<m;++i) r.g[i]=g[i];
        return r;
    }
    };
    arr<num> one_n,zero_n;
    arr<short> one_i,zero_i;
    template<class T>
    arr<T> operator + (arr<T> a,arr<T> b)
    {
        for(int i=0;i<m;++i)
            a.g[i]=(int(a.g[i])+b.g[i])%MOD;
        return a;
    }
    template<class T>
    arr<T> operator - (arr<T> a,arr<T> b)
    {
        for(int i=0;i<m;++i)
            a.g[i]=(int(a.g[i])+MOD-b.g[i])%MOD;
        return a;
    }
    arr<num> operator * (arr<num> a,arr<num> b)
    {
        for(int i=0;i<m;++i)
            a.g[i]=a.g[i]*b.g[i];
        return a;
    }
    arr<short> operator * (arr<short> a,arr<short> b)
    {
        for(int i=0;i<m;++i)
            a.g[i]=a.g[i]*(int)b.g[i]%MOD;
        return a;
    }
    arr<num> operator / (arr<num> a,arr<num> b)
    {
        for(int i=0;i<m;++i)
            a.g[i]=a.g[i]/b.g[i];
        return a;
    }
    struct mat
    {
    arr<short> g00,g01,g20,g21;
    /*
    x y 0
    0 1 0
    z s 1
    */
    };
    mat operator * (mat a,mat b)
    {
        mat p;
        p.g00=a.g00*b.g00;
        p.g01=a.g00*b.g01+a.g01;
        p.g20=a.g20*b.g00+b.g20;
        p.g21=a.g20*b.g01+a.g21+b.g21;
        return p;
    }
    //pair(w,s)
    pair<arr<short>,arr<short> > cp(mat s)
    {
        return make_pair(s.g00+s.g01,s.g20+s.g21);
    }
    inline mat gs(arr<short> x)
    {
        mat s;
        s.g01=s.g21=one_i;
        s.g00=s.g20=x; return s;
    }
    arr<short> sw,isw; //sum of w[i]
    arr<num> v[SZ],g[SZ],w[SZ]; mat gm[SZ]; //重链顶端的w保证正确
    int fa[SZ],son[SZ],sz[SZ],top[SZ],fi[SZ],bt[SZ],C=0;
    arr<num> ts[130];
    void dfs(int x,int f=0)
    {
        fa[x]=f; sz[x]=1;
        for esb(x,e,b) if(b!=f)
        {
            dfs(b,x),sz[x]+=sz[b];
            if(sz[b]>sz[son[x]]) son[x]=b;
        }
    }
    void dfs2(int x,int t,int f=0)
    {
        top[x]=t; fi[x]=++C; bt[t]=C;
        if(!son[x]) return;
        dfs2(son[x],t,x);
        for esb(x,e,b) if(b!=f&&b!=son[x])
            dfs2(b,b,x);
    }
    const int Z=32768;
    mat seg[Z+Z+3],I;
    void dfs3(int x,int f=0,int d=0)
    {
        for esb(x,e,b) if(b!=f) dfs3(b,x,d+1);
        g[x]=v[x];
        for esb(x,e,b) if(b!=f) g[x]=g[x]*w[b];
        w[x]=g[x]+one_n; if(son[x]) g[x]=g[x]/w[son[x]];
        seg[Z+fi[x]]=gm[x]=gs(g[x]); sw=sw+arr<short>(w[x]);
    }
    void upd(int x)
    {
        for((x+=Z)>>=1;x;x>>=1) seg[x]=seg[x+x]*seg[x+x+1];
    }
    mat qry(int l,int r)
    {
        mat rs=I; static int st[SZ]; int sn=0;
        for(l+=Z-1,r+=Z+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1) rs=rs*seg[l^1];
            if(r&1) st[++sn]=r^1;
        }
        while(sn) rs=rs*seg[st[sn--]];
        return rs;
    }
    int main()
    {
        inv[1]=1;
        for(int i=2;i<MOD;++i)
            inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
        scanf("%d%d",&n,&m);
        static int a[SZ];
        for(int i=1;i<=n;++i) scanf("%d",a+i);
        for(int i=1;i<n;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            adde(a,b);
        }
        for(int i=0;i<m;++i) one_n.g[i]=1,zero_n.g[i]=0;
        for(int i=0;i<m;++i) one_i.g[i]=1,zero_i.g[i]=0;
        I.g00=one_i; I.g01=I.g20=I.g21=zero_i;
        sw=zero_i; dfs(1); dfs2(1,1);
        for(int i=0;i<m;++i)
            ts[i]=zero_n, ts[i].g[i]=1, ts[i].fwt();
        for(int i=1;i<=n;++i) v[i]=ts[a[i]];
        dfs3(1); isw=sw; isw.ifwt();
        for(int i=Z-1;i>=1;--i)
            seg[i]=seg[i+i]*seg[i+i+1];
        int q; scanf("%d",&q);
        while(q--)
        {
            char s[10]; scanf("%s",s);
            if(s[0]=='Q')
            {
                int a; scanf("%d",&a);
                ll ans=isw.g[a];
                if(!a) ans-=n;
                ans=(ans%MOD+MOD)%MOD;
                printf("%d
    ",int(ans));
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                mat r=qry(fi[top[x]],bt[top[x]]);
                pair<arr<short>,arr<short> > s=cp(r); sw=sw-s.se;
                g[x]=g[x]/v[x]*ts[y]; v[x]=ts[y];
                seg[Z+fi[x]]=gm[x]=gs(g[x]); upd(fi[x]); x=top[x];
                r=qry(fi[top[x]],bt[top[x]]);
                s=cp(r); sw=sw+s.se;
                while(fa[x])
                {
                    int y=fa[x]; g[y]=g[y]/w[x]*arr<num>(s.fi);
                    w[x]=s.fi; x=y;
                    r=qry(fi[top[x]],bt[top[x]]);
                    s=cp(r); sw=sw-s.se;
                    seg[Z+fi[x]]=gm[x]=gs(g[x]); upd(fi[x]); x=top[x];
                    r=qry(fi[top[x]],bt[top[x]]);
                    s=cp(r); sw=sw+s.se;
                }
                w[x]=s.fi; isw=sw; isw.ifwt();
            }
        }
    }

    D2T1 天才黑客

    好像这种做法不是最优的,比标解多了一个log的样子。

    考虑把边拆点,拆成入点和出点,中间连边权。然后1号点连上入点,出点连上边另一个端点。接下来我们要做的就是把同一个点的入边的出点 和 出边的入点 之间连边。

    考虑把这些点提取出来在字典树上建个虚树,然后连边的话考虑lca为一个点的有哪些点对,要么是子树之间的,要么是自己和整棵树之间的,在dfs序上建两棵线段树辅助一下连边就好了。

    代码难度还是挺高的...

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 2000000
    int N=0;
    #define SS 3500000
    int M=0,fst[SS],vb[SS],nxt[SS],vc[SS];
    void ad_de(int a,int b,int c=0){if(a&&b);else return;
    //cout<<a<<"->"<<b<<"[label="<<c<<"]
    ";
    ++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b; vc[M]=c;}
    void ad_fe(int a,int b,int c=0) {ad_de(b,a,c);}
    typedef pair<ll,int> pii;
    ll dist[SS];
    #define fi first
    #define se second
    void dj()
    {
        priority_queue<pii,vector<pii>,greater<pii> > pq;
        for(int i=1;i<=N;++i) dist[i]=1e18;
        dist[1]=0; pq.push(pii(0,1));
        while(!pq.empty())
        {
            pii t=pq.top(); pq.pop();
            if(t.fi!=dist[t.se]) continue;
            int x=t.se;
            for(int e=fst[x];e;e=nxt[e])
            {
                int b=vb[e];
                if(dist[b]<=dist[x]+vc[e])
                    continue;
                dist[b]=dist[x]+vc[e];
                pq.push(pii(dist[b],b));
            }
        }
    }
    template<void f(int,int,int)>
    struct seg
    {
    int Z,s[SZ];
    void init(int n)
    {
        Z=1; while(Z<=n+3) Z<<=1;
        for(int i=1;i<=Z+Z;++i) s[i]=++N;
        for(int i=Z-1;i>=1;--i)
            f(s[i],s[i+i],0),f(s[i],s[i+i+1],0);
    }
    int gr(int l,int r)
    {
        int p=++N;
        if(l>r) return p;
        for(l+=Z-1,r+=Z+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1) f(p,s[l^1],0);
            if(r&1) f(p,s[r^1],0);
        }
        return p;
    }
    };
    seg<ad_de> zs;
    seg<ad_fe> fs;
    int fl[SZ];
    namespace vt
    {
    Edg
    int C,df[SZ],ls[SZ];
    void dfs(int x)
    {
        df[x]=++C;
        for esb(x,e,b) dfs(b);
        ls[x]=C;
    }
    void dfs2(int x)
    {
        int l=df[x],r=df[x];
        ::ad_de(fs.gr(l,r),zs.gr(l,r),fl[x]);
        for esb(x,e,b) dfs2(b);
        for esb(x,e,b)
        {
            ::ad_de(fs.gr(l,r),zs.gr(df[b],ls[b]),fl[x]),
            ::ad_de(fs.gr(df[b],ls[b]),zs.gr(l,r),fl[x]);
            r=ls[b];
        }
    }
    void doit(int r)
    {
        C=0; dfs(r); zs.init(C);
        fs.init(C); dfs2(r);
    }
    }
    namespace rt
    {
    Edg
    int n,dfn[SZ],C=0,sz[SZ],son[SZ];
    void dfs(int x,int f=0)
    {
        if(f) fl[x]=fl[f]+1; dfn[x]=++C; sz[x]=1; son[x]=0;
        for esb(x,e,b)
        {
            dfs(b,x); sz[x]+=sz[b];
            if(sz[b]>sz[son[x]]) son[x]=b;
        }
    }
    int top[SZ],fa[SZ];
    void dfs2(int x,int t,int f=0)
    {
        fa[x]=f; top[x]=t;
        if(!son[x]) return;
        dfs2(son[x],t,x);
        for esb(x,e,b) if(b!=son[x]) dfs2(b,b,x);
    }
    int lca(int a,int b)
    {
        while(top[a]!=top[b])
            if(fl[top[a]]<fl[top[b]]) b=fa[top[b]];
            else a=fa[top[a]];
        return (fl[a]<fl[b])?a:b;
    }
    bool cmp(int a,int b) {return dfn[a]<dfn[b];}
    void init()
    {
        C=M=0;
        for(int i=1;i<=n;++i) fst[i]=0;
        for(int i=1;i<n;++i)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            ad_de(a,b);
        }
        dfs(1);dfs2(1,1);
    }
    int vs[SZ],st[SZ],vn=0,stn=0,vfa[SZ];
    void buildrt(int*g,int gn)
    {
        sort(g+1,g+1+gn,cmp);
        gn=unique(g+1,g+1+gn)-g-1;
        vn=stn=0;
        for(int i=1;i<=gn;i++) vs[++vn]=g[i],vfa[g[i]]=0;
        for(int i=1;i<=gn;i++)
        {
            int x=g[i];
            if(!stn) {st[++stn]=x; vfa[x]=0; continue;}
            int lca=rt::lca(x,st[stn]);
            for(;fl[st[stn]]>fl[lca];--stn)
                if(fl[st[stn-1]]<=fl[lca])
                    vfa[st[stn]]=lca;
            if(st[stn]!=lca)
            {
                vs[++vn]=lca;
                vfa[lca]=st[stn];
                st[++stn]=lca;
            }
            vfa[x]=lca; st[++stn]=x;
        }
        int ro=0; vt::M=0;
        for(int i=1;i<=vn;++i)
            vt::fst[vs[i]]=0;
        for(int i=1;i<=vn;++i)
            if(vfa[vs[i]]) vt::ad_de(vfa[vs[i]],vs[i]); else ro=vs[i];
        vt::doit(ro);
    }
    }
    namespace Sol
    {
    int n,m,k,ea[SZ],eb[SZ],ec[SZ],ed[SZ],i1[SZ],i2[SZ];
    namespace Z{Edgc}
    namespace F{Edgc}
    void sol()
    {
        scanf("%d%d%d",&n,&m,&k); Z::M=F::M=0;
        ::M=0; ::N=n; memset(::fst,0,sizeof ::fst);
        for(int i=1;i<=n;++i) Z::fst[i]=F::fst[i]=0;
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d%d",ea+i,eb+i,ec+i,ed+i);
            Z::ad_de(ea[i],eb[i],i);
            F::ad_de(eb[i],ea[i],i);
            i1[i]=++N; i2[i]=++N;
            ad_de(i1[i],i2[i],ec[i]);
            if(ea[i]==1) ad_de(1,i1[i]);
            ad_de(i2[i],eb[i]);
        }
        rt::n=k; rt::init();
        for(int i=1;i<=n;++i)
        {
            static int tmp[SZ]; int tn=0;
            for(int e=Z::fst[i];e;e=Z::nxt[e])
                tmp[++tn]=ed[Z::vc[e]];
            for(int e=F::fst[i];e;e=F::nxt[e])
                tmp[++tn]=ed[F::vc[e]];
            rt::buildrt(tmp,tn);
            for(int e=F::fst[i];e;e=F::nxt[e])
                ad_de(i2[F::vc[e]],fs.s[vt::df[ed[F::vc[e]]]+fs.Z]);
            for(int e=Z::fst[i];e;e=Z::nxt[e])
                ad_de(zs.s[zs.Z+vt::df[ed[Z::vc[e]]]],i1[Z::vc[e]]);
        }
        dj();
        for(int i=2;i<=n;++i)
            printf("%lld
    ",dist[i]);
    }
    }
    int main()
    {
        int T; scanf("%d",&T);
        for(int i=1;i<=T;++i) Sol::sol();
    }

    D2T2 遗忘的集合

    euler transform裸题,详见 http://l0nl1f3.leanote.com/post/Euler-Transform-discussion

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 666666
    
    //mtt
    #define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i)
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define mp make_pair
    #define x first
    #define y second
    #define pb push_back
    #define ALL(x) (x).begin(), (x).end()
    
    template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
    template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
    
    typedef long long LL;
    
    const int oo = 0x3f3f3f3f;
    
    int Mod = 1e9 + 7;
    #define MOD Mod
    ll qp(ll a,ll b)
    {
        ll x=1;
        while(b)
        {
            if(b&1) x=x*a%MOD;
            a=a*a%MOD; b>>=1;
        }
        return x;
    }
    const int max0 = 524288;
    
    struct comp
    {
        double x, y;
    
        comp(): x(0), y(0) { }
        comp(const double &_x, const double &_y): x(_x), y(_y) { }
    
    };
    
    inline comp operator+(const comp &a, const comp &b) { return comp(a.x + b.x, a.y + b.y); }
    inline comp operator-(const comp &a, const comp &b) { return comp(a.x - b.x, a.y - b.y); }
    inline comp operator*(const comp &a, const comp &b) { return comp(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); }
    inline comp conj(const comp &a) { return comp(a.x, -a.y); }
    
    const double PI = acos(-1);
    
    int N,L;
    
    comp w[max0 + 5];
    int bitrev[max0 + 5];
    
    void fft(comp *a, const int &n)
    {
        REP(i, 0, n) if (i < bitrev[i]) swap(a[i], a[bitrev[i]]);
        for (int i = 2, lyc = n >> 1; i <= n; i <<= 1, lyc >>= 1)
            for (int j = 0; j < n; j += i)
            {
                comp *l = a + j, *r = a + j + (i >> 1), *p = w;
                REP(k, 0, i >> 1)
                {
                    comp tmp = *r * *p;
                    *r = *l - tmp, *l = *l + tmp;
                    ++l, ++r, p += lyc;
                }
            }
    }
    
    inline void fft_prepare()
    {
        REP(i, 0, N) bitrev[i] = bitrev[i >> 1] >> 1 | ((i & 1) << (L - 1));
        REP(i, 0, N) w[i] = comp(cos(2 * PI * i / N), sin(2 * PI * i / N));
    }
    
    inline void conv(int *x, int *y, int *z)
    {
        REP(i, 0, N) (x[i] += Mod) %= Mod, (y[i] += Mod) %= Mod;
        static comp a[max0 + 5], b[max0 + 5];
        static comp dfta[max0 + 5], dftb[max0 + 5], dftc[max0 + 5], dftd[max0 + 5];
    
        REP(i, 0, N) a[i] = comp(x[i] & 32767, x[i] >> 15);
        REP(i, 0, N) b[i] = comp(y[i] & 32767, y[i] >> 15);
        fft(a, N), fft(b, N);
        REP(i, 0, N)
        {
            int j = (N - i) & (N - 1);
            static comp da, db, dc, dd;
            da = (a[i] + conj(a[j])) * comp(0.5, 0);
            db = (a[i] - conj(a[j])) * comp(0, -0.5);
            dc = (b[i] + conj(b[j])) * comp(0.5, 0);
            dd = (b[i] - conj(b[j])) * comp(0, -0.5);
            dfta[j] = da * dc;
            dftb[j] = da * dd;
            dftc[j] = db * dc;
            dftd[j] = db * dd;
        }
        REP(i, 0, N) a[i] = dfta[i] + dftb[i] * comp(0, 1);
        REP(i, 0, N) b[i] = dftc[i] + dftd[i] * comp(0, 1);
        fft(a, N), fft(b, N);
        REP(i, 0, N)
        {
            int da = (LL)(a[i].x / N + 0.5) % Mod;
            int db = (LL)(a[i].y / N + 0.5) % Mod;
            int dc = (LL)(b[i].x / N + 0.5) % Mod;
            int dd = (LL)(b[i].y / N + 0.5) % Mod;
            z[i] = (da + ((LL)(db + dc) << 15) + ((LL)dd << 30)) % Mod;
        }
    }
    int x[SZ],g[SZ],tmp[SZ],tx[SZ],d[SZ],r[SZ];
    void ginv(int s)
    {
        if(s==0)
        {
            g[0]=qp(x[0],Mod-2);
            return;
        }
        ginv(s-1);
        L=s+1; N=1LL<<L; fft_prepare();
        for(int i=N/4;i<N;++i) g[i]=0;
        for(int i=0;i<N/2;++i) tx[i]=x[i];
        conv(tx,g,tmp);
        for(int i=N/2;i<N;++i) tmp[i]=0;
        for(int i=0;i<N;++i) tmp[i]=((i?0:2)-tmp[i]+MOD)%MOD;
        conv(g,tmp,g);
        for(int i=N/2;i<N;++i) g[i]=0;
    }
    int n,rs[SZ];
    int main()
    {
        scanf("%d%d",&n,&MOD); ++n; x[0]=1;
        for(int i=1;i<n;++i) scanf("%d",x+i);
        int s=0;
        while(n>(1<<s)) ++s;
        ginv(s);
        L=s+1; N=1<<L; fft_prepare();
        for(int i=1;i<n;++i) d[i-1]=x[i]*ll(i)%MOD;
        conv(d,g,r);
        vector<int> ans;
        for(int i=1;i<n;++i)
        {
            rs[i]=(r[i-1]-rs[i]+MOD)%MOD;
            for(int j=i+i;j<=n;j+=i) (rs[j]+=rs[i])%=MOD;
            if(rs[i]) ans.pb(i);
        }
        printf("%d
    ",int(ans.size()));
        for(unsigned j=0;j<ans.size();++j)
            printf("%d ",ans[j]);puts("");
    }

    D2T3 文本校正

    假设把原串切成123,那么有以下拼合方法:

    123 (那可真蠢)

    231、312 (枚举个切分点切开,然后哈希判一判)

    213:枚举3的位置,然后可以发现1和2的长度的可能取值必须是两个前缀的最大匹配之一,证明参见相关题目题解,kmp+hash即可。

    132:把上面一个倒过来。

    321:考虑把两个串做C变换(C(a,b)=a[1]b[n]a[2]b[n-1]...a[n]b[1]),然后就是要判断这个玩意儿是不是一个三偶回文串。枚举一个切分点,就是要看后缀是不是双偶回文串,两个回文串中至少有一个可以是最长回文前缀/最长回文后缀,最长回文后缀直接暴力判,最长回文前缀跑完manacher之后更新一遍。(我们需要知道以每个下标作为左端点的最长回文串。从右到左扫描,维护一下当前的左边界,做第i位时我们只要更新当前i-p[i]~左边界-1这一段,然后更新左边界。正确性显然。)

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #define VIZ2 {printf("graph G{
    "); for(int i=1;i<=n;i++) for es(i,e) if(vb[e]>=i)printf("%d--%d;
    ",i,vb[e]); puts("}");}
    #define SZ 4444444
    int l[3],r[3];
    int T,n,m;
    const int MOD=666623333,S=10000007;
    ll po[SZ];
    template<const int G>
    struct str
    {
    int s[G],n;
    ll qz[G];
    int fail[G],pal[G],sp[G];
    void mlc() //malache
    {
        int ml=0,p=0; s[n+1]=-1;s[0]=-2;
        for(int i=1;i<=n;++i)
        {
            if(i<=ml) pal[i]=min(pal[p+p-i],ml-i);
            else pal[i]=0;
            while(i>=pal[i]+1&&
            s[i-pal[i]-1]==s[i+pal[i]+1])
                ++pal[i];
            if(i+pal[i]>ml)
                ml=i+pal[i],p=i;
        }
        for(int i=n;i>=1;--i) sp[i]=0;
        int cl=n+1;
        for(int i=n;i>=1;--i)
        {
            for(int j=min(cl-1,i);j>=i-pal[i];--j)
                cl=j,sp[j]=max(sp[j],i-j);
        }
    }
    void init()
    {
        for(int i=1;i<=n;++i)
            qz[i]=(qz[i-1]*S+s[i])%MOD;
        fail[1]=0;
        for(int i=2,j=0;i<=n;++i)
        {
            while(j&&s[j+1]!=s[i]) j=fail[j];
            if(s[j+1]==s[i]) ++j; fail[i]=j;
        }
    }
    inline ll hsh(int l,int r)
    {
        ll rs=qz[r]-qz[l-1]*po[r-l+1];
        rs%=MOD; return (rs<0)?(rs+MOD):rs;
    }
    void r()
    {
        reverse(s+1,s+1+n);
    }
    const str& operator = (const str<G>& b)
    {
        n=b.n; memcpy(s,b.s,sizeof(int)*(n+2));
    }
    };
    str<1000005> a,b,ra,rb;
    bool w213(str<1000005>&a,str<1000005>&b)
    {
        int o=n+1;
        for(int i=n;i>=3&&a.s[i]==b.s[i];--i) o=i;
        for(int i=1,j=0;i<n;++i)
        {
            while(j&&a.s[j+1]!=b.s[i]) j=a.fail[j];
            if(a.s[j+1]==b.s[i]) ++j;
            if(i+1<o||!j) continue;
            if(a.hsh(j+1,i)==b.hsh(1,i-j))
            {
                l[0]=1; r[0]=j;
                l[1]=j+1; r[1]=i;
                l[2]=i+1; r[2]=n;
                return 1;
            }
        }
        for(int i=1,j=0;i<n;++i)
        {
            while(j&&b.s[j+1]!=a.s[i]) j=b.fail[j];
            if(b.s[j+1]==a.s[i]) ++j;
            if(i+1<o||!j) continue;
            if(b.hsh(j+1,i)==a.hsh(1,i-j))
            {
                l[0]=1; r[0]=i-j;
                l[1]=i-j+1; r[1]=i;
                l[2]=i+1; r[2]=n;
                return 1;
            }
        }
        return 0;
    }
    str<2000005> t,rt;
    str<4000005> tt;
    bool w321()
    {
        t.n=0;
        for(int i=1;i<=n;++i)
            t.s[++t.n]=a.s[i],
            t.s[++t.n]=b.s[n+1-i];
        rt=t; rt.r(); t.init(); rt.init();
        tt.n=0; tt.s[++tt.n]=m+1;
        for(int i=1;i<=t.n;++i)
            tt.s[++tt.n]=t.s[i],tt.s[++tt.n]=m+1;
        tt.mlc();
        int rm=0;
        for(int r=n+n;r>=2;--r)
        {
            if(t.hsh(r,n+n)==rt.hsh(1,n+n-r+1)) rm=n+n-r+1;
            int gs=tt.sp[r*2-1]/2*2;
            if(r&1);else continue;
            //case1: r-1|...|rm
            {
                int a=r-1,c=rm,b=n+n-a-c;
                if(a>0&&b>0&&c>0&&a%2==0&&b%2==0&&c%2==0&&
                t.hsh(1,a)==rt.hsh(n+n-a+1,n+n)
                &&t.hsh(a+1,a+b)==rt.hsh(n+n-a-b+1,n+n-a)
                //&&t.hsh(n+n-c+1,n+n)==rt.hsh(1,c)
                )
                {
                    a/=2,b/=2,c/=2;
                    l[0]=1; ::r[0]=a;
                    l[1]=a+1; ::r[1]=a+b;
                    l[2]=a+b+1; ::r[2]=n;
                    return 1;
                }
            }
            //case2: r-1|gs|...
            {
                int a=r-1,b=gs,c=n+n-a-b;
                if(a>0&&b>0&&c>0&&a%2==0&&b%2==0&&c%2==0&&
                t.hsh(1,a)==rt.hsh(n+n-a+1,n+n)
                &&t.hsh(a+1,a+b)==rt.hsh(n+n-a-b+1,n+n-a)
                &&t.hsh(n+n-c+1,n+n)==rt.hsh(1,c)
                )
                {
                    a/=2,b/=2,c/=2;
                    l[0]=1; ::r[0]=a;
                    l[1]=a+1; ::r[1]=a+b;
                    l[2]=a+b+1; ::r[2]=n;
                    return 1;
                }
            }
        }
        return 0;
    }
    namespace FF
    {
    char ch,B[1<<20],*S=B,*T=B;
    #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<20,stdin),S==T)?0:*S++)
    #define isd(c) (c>='0'&&c<='9')
    int aa,bb;int F(){
        while(ch=getc(),!isd(ch)&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
        while(ch=getc(),isd(ch))aa=aa*10+ch-'0';return bb?aa:-aa;
    }
    }
    #define gi FF::F()
    void sol()
    {
        n=gi,m=gi; a.n=b.n=ra.n=rb.n=n;
        for(int i=1;i<=n;++i) b.s[i]=gi;
        for(int i=1;i<=n;++i) a.s[i]=gi;
        ra=a; rb=b; ra.r(); rb.r();
        a.init(); b.init(); ra.init(); rb.init();
        l[0]=r[0]=-1;
        if(n<3)
        {
            puts("NO");
            return;
        }
        bool s=1;
        for(int i=1;i<=n;++i) s&=a.s[i]==b.s[i];
        if(s)
        {
            puts("YES");
            puts("1 1");
            puts("2 2");
            printf("3 %d
    ",n);
            return;
        }
        for(int i=1;i<n;++i)
        {
            if(a.hsh(1,i)==b.hsh(n-i+1,n)&&
            a.hsh(i+1,n)==b.hsh(1,n-i))
            {
                if(i!=1)
                {
                    puts("YES");
                    printf("%d %d
    ",i+1,n);
                    puts("1 1");
                    printf("2 %d
    ",i);
                    return;
                }
                else
                {
                    puts("YES");
                    printf("%d %d
    ",i+1,i+1);
                    printf("%d %d
    ",i+2,n);
                    puts("1 1");
                    return;
                }
            }
        }
        bool f=w213(a,b);
        if(f)
        {
            puts("YES");
            printf("%d %d
    ",l[1],r[1]);
            printf("%d %d
    ",l[0],r[0]);
            printf("%d %d
    ",l[2],r[2]);
            return;
        }
        f=w213(ra,rb);
        if(f)
        {
            for(int i=0;i<3;++i)
                l[i]=n+1-l[i],r[i]=n+1-r[i],
                swap(l[i],r[i]);
            puts("YES");
            printf("%d %d
    ",l[2],r[2]);
            printf("%d %d
    ",l[0],r[0]);
            printf("%d %d
    ",l[1],r[1]);
            return;
        }
        f=w321();
        if(f)
        {
            puts("YES");
            printf("%d %d
    ",l[2],r[2]);
            printf("%d %d
    ",l[1],r[1]);
            printf("%d %d
    ",l[0],r[0]);
            return;
        }
        puts("NO");
    }
    int main()
    {
        po[0]=1;
        for(int i=1;i<SZ;++i)
            po[i]=po[i-1]*S%MOD;
        T=gi;
        while(T--) sol();
    }

    image

    完结撒花

  • 相关阅读:
    消息循环中的TranslateMessage函数和DispatchMessage函数,特别注意WM_TIMER消息
    单线程程序处理消息的方式!
    PeekMessage&GetMessage
    GetTickCount() 函数的作用和用法
    LPVOID 没有类型的指针
    sprintf详解
    memset用法详解
    C语言中%d,%o,%f,%e,%x的意义
    VS2013 C++ 动态链接库的生成
    visual studio 2013的C++开发环境不错--vs2013安装试用手记
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/7523003.html
Copyright © 2020-2023  润新知