NOI模拟16

山东省选的day2,T1似乎挺签到的,但是我因为没有看出来一个结论于是就没哟写

T2有意思,我写了虚树+LCT,但是必须要离线,在luogu没有前途

T1 小N的独立集

这个原dp是一个经典dp,所以实际上就是个dp套dp

dp[i][j][k]表示走到i点时,选i最大是j的贡献,不选是k贡献

发现\(k>=j-v_i\),但是我们并不知道上界,但是我们发现当k>j是j就没有用了,所以我们可以只记录k

发现这样写比较难写,我们转换一下dp定义,dp[i][j][k]表示走到i点,强制不选i点的最大贡献是j,不强制的最大贡献是k

此时发现j的状态完全被k包含了,转移就非常的简洁了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=1005;
const int mod=1e9+7;
int n,k;
struct E{int to,nxt;}e[N*2];
int head[N],rp;
void add_edg(int x,int y){e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;}
int dp[N][N*5][7],siz[N],g[2][N*5][7],ans[N*5];
void dfs(int x,int f){
    siz[x]=1;
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;
        if(y==f)continue;
        dfs(y,x);siz[x]+=siz[y];
    }
    int now=0;memset(g,0,sizeof(g));
    fo(i,1,k)g[now][0][i]=1;
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;if(y==f)continue;
        now^=1;memset(g[now],0,sizeof(g[now]));
        fo(l,0,k*siz[x])fo(r,0,k)if(g[now^1][l][r]){
            // cerr<<"SB"<<endl;
            fo(p,0,k*siz[y])fo(q,0,k)if(dp[y][p][q]){
                // cerr<<"SB"<<endl;
                g[now][l+p+q][max(l+p+q,l+r+p)-(l+p+q)]=(g[now][l+p+q][max(l+p+q,l+r+p)-(l+p+q)]+g[now^1][l][r]*dp[y][p][q])%mod;
            }
        }
    }
    fo(l,0,k*siz[x])fo(r,0,k)dp[x][l][r]=g[now][l][r];
    // cerr<<x<<" "<<dp[x][0][1]<<endl;
}
signed main(){
    freopen("nset.in","r",stdin);
    freopen("nset.out","w",stdout);
    n=read();k=read();
    fo(i,1,n-1){
        int x=read(),y=read();
        add_edg(x,y);add_edg(y,x);
    }
    dfs(1,0);
    fo(i,0,k*n)fo(r,0,k){
        ans[i+r]=(ans[i+r]+dp[1][i][r])%mod;
    }
    fo(i,1,k*n)printf("%lld\n",ans[i]);
    return 0;
}

T2 无处存储

就是写一下我的LCT,正解我并不会

询问非常少,可以对询问建立虚树,所以离线,用LCT维护这个虚树

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ui unsigned int
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
ui lak[14000010],now;
ui *fa,*siz,*dfn,*dep,*a;
ui id,n,m,A,B,C,a0;
ui *w,cw,*sta,tp;
struct Q{ui tp,x,y,v;}q[50001];
bool com(ui x,ui y){return dfn[x]<dfn[y];}
ui LCA(ui x,ui y){
    if(dep[x]<dep[y])swap(x,y);
    // bool fl=false;
    // if(x==10&&y==2){
    //     cerr<<"SB"<<endl;
    //     fl=true;
    // }
    while(dep[x]>dep[y])x=fa[x];
    // if(fl)cerr<<x<<" "<<y<<endl;
    while(x!=y)x=fa[x],y=fa[y];
    return x;
}
ui DIS(ui x,ui y){
    ui ret=0,res=0;
    if(dep[x]<dep[y])swap(x,y);
    while(dep[x]>dep[y])x=fa[x],ret++;
    while(x!=y)x=fa[x],y=fa[y],ret+=2;
    return ret-1;
}
ui *lsh,*sz;
struct LCT{
    struct POT{
        ui son[2],fa;
        ui vl,sz;bool rev;
    }tr[400005];
    ui pth[400005],pt,al,*sm,*tg;
    void add_edg(ui x,ui y,ui z){
        // cerr<<x<<" "<<y<<" "<<" "<<z<<endl;
        // cerr<<lsh[x]<<" "<<lsh[y]<<endl;
        tr[y].fa=++al;
        tr[al].fa=x;
        sz[al]=z;sz[x]=sz[y]=1;
    }
    void pushup(ui x){
        sm[x]=sm[tr[x].son[0]]+sm[tr[x].son[1]]+tr[x].vl;
        tr[x].sz=tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz+sz[x];
    }
    void pushr(ui x){
        swap(tr[x].son[0],tr[x].son[1]);
        tr[x].rev^=1;
    }
    void pusht(ui x,ui v){
        tr[x].vl+=sz[x]*v;
        sm[x]+=tr[x].sz*v;
        tg[x]+=v;
    }
    void pushdown(ui x){
        if(tr[x].rev){
            if(tr[x].son[0])pushr(tr[x].son[0]);
            if(tr[x].son[1])pushr(tr[x].son[1]);
            tr[x].rev=0;
        }
        if(tg[x]){
            if(tr[x].son[0])pusht(tr[x].son[0],tg[x]);
            if(tr[x].son[1])pusht(tr[x].son[1],tg[x]);
            tg[x]=0;
        }
    }
    bool nroot(ui x){return tr[tr[x].fa].son[0]==x||tr[tr[x].fa].son[1]==x;}
    bool get(ui x){return tr[tr[x].fa].son[1]==x;}
    void rotate(ui x){
        ui y=tr[x].fa,z=tr[y].fa;
        ui xpos=get(x),ypos=get(y);
        if(nroot(y))tr[z].son[ypos]=x;
        tr[x].fa=z;tr[y].fa=x;
        tr[y].son[xpos]=tr[x].son[xpos^1];
        tr[tr[y].son[xpos]].fa=y;
        tr[x].son[xpos^1]=y;
        pushup(y);pushup(x);
    }
    void splay(ui x){
        ui now=x;pth[++pt]=x;
        while(nroot(now))pth[++pt]=now=tr[now].fa;
        while(pt)pushdown(pth[pt--]);
        while(nroot(x)){
            ui y=tr[x].fa;
            if(nroot(y)){
                if(get(x)==get(y))rotate(y);
                else rotate(x);
            }rotate(x);
        }pushup(x);
    }
    void access(ui x){
        for(ui y=0;x;y=x,x=tr[x].fa){
            splay(x);tr[x].son[1]=y;pushup(x);
        }
    }
    void makeroot(ui x){
        access(x);splay(x);pushr(x);
    }
    void split(ui x,ui y){
        makeroot(x);access(y);splay(y);
    }
}lct;
ui iid(ui x){return lower_bound(lsh+1,lsh+cw+1,x)-lsh;}
void build_vtree(){
    // cerr<<cw<<endl;fo(i,1,cw)cerr<<w[i]<<endl;
    sort(w+1,w+cw+1,com);cw=unique(w+1,w+cw+1)-w-1;
    // cerr<<cw<<endl;fo(i,1,cw)cerr<<w[i]<<endl;
    ui nn=cw;fo(i,1,nn-1)w[++cw]=LCA(w[i],w[i+1]);//cerr<<w[cw]<<" "<<w[i]<<" "<<w[i+1]<<endl;
    sort(w+1,w+cw+1,com);cw=unique(w+1,w+cw+1)-w-1;
    // cerr<<"ZZ"<<endl;
    // cerr<<cw<<endl;fo(i,1,cw)cerr<<w[i]<<endl;
    fo(i,1,cw)lsh[i]=w[i];
    sort(lsh+1,lsh+cw+1);
    // cerr<<w[1]<<endl;
    sta[tp=1]=w[1];lct.al=cw;
    fo(i,2,cw){
        // cerr<<i<<" "<<cw<<endl;
        ui lca=LCA(sta[tp],w[i]);
        if(lca!=sta[tp]){
            while(dfn[lca]<dfn[sta[tp-1]]){
                // cerr<<sta[tp-1]<<" "<<sta[tp]<<" "<<iid(sta[tp])<<endl;
                lct.add_edg(iid(sta[tp-1]),iid(sta[tp]),DIS(sta[tp-1],sta[tp]));
                tp--;
            }
            // cerr<<lca<<" "<<sta[tp]<<endl;
            if(dfn[lca]!=dfn[sta[tp-1]]){
                // cerr<<lca<<" "<<sta[tp]<<endl;
                lct.add_edg(iid(lca),iid(sta[tp]),DIS(lca,sta[tp]));
                sta[tp]=lca;
            }
            else lct.add_edg(iid(lca),iid(sta[tp]),DIS(lca,sta[tp])),tp--;
        }
        sta[++tp]=w[i];
    }
    fo(i,1,tp-1){
        // cerr<<sta[i]<<" "<<sta[i+1]<<endl;
        lct.add_edg(iid(sta[i]),iid(sta[i+1]),DIS(sta[i],sta[i+1]));
    }
    a=dfn;a[0]=a0;fo(i,1,n)a[i]=a[i-1]*a[i-1]*A+a[i-1]*B+C;
    // cerr<<"SB"<<endl;
    fo(i,1,cw){
        // cerr<<i<<" "<<cw<<endl;
        lct.tr[i].vl=a[lsh[i]];
        if(lct.tr[i].fa){
            ui ok=lsh[lct.tr[lct.tr[i].fa].fa],now=fa[lsh[i]];
            // cerr<<lsh[i]<<" "<<fa[lsh[i]]<<" "<<lct.tr[i].fa<<" "<<ok<<endl;
            while(now!=ok){
                // cerr<<now<<endl;
                lct.tr[lct.tr[i].fa].vl+=a[now];
                now=fa[now];
            }
        }
    }
}
void sol1(){
    // cerr<<"SB"<<endl;
    dfn=lak+now;now+=n+5;
    siz=lak+now;now+=n+5;
    fu(i,n,1)siz[i]++,siz[fa[i]]+=siz[i];
    fo(i,1,n){
        dfn[i]=dfn[fa[i]]+1;
        if(fa[i])dfn[fa[i]]+=siz[i];
    }
    // cerr<<"SB"<<endl;
    fo(i,1,n)dfn[i]-=siz[i]-1;//cerr<<dfn[i]<<" ";cerr<<endl;
    w=lak+now;now+=m*4+5;
    fo(i,1,m){
        scanf("%u%u%u",&q[i].tp,&q[i].x,&q[i].y);
        if(q[i].tp==0)scanf("%u",&q[i].v);
        w[++cw]=q[i].x;w[++cw]=q[i].y;
        // cerr<<q[i].x<<" "<<q[i].y<<endl;
    }
    // cerr<<w[1]<<endl;
    // cerr<<"SB"<<endl;
    dep=siz;fo(i,1,n)dep[i]=dep[fa[i]]+1;
    sta=lak+now;now+=m*4+5;
    // cerr<<cw<<endl;
    lsh=lak+now;now+=m*4+5;
    sz=lak+now;now+=m*8+5;
    lct.sm=lak+now;now+=m*8+5;
    lct.tg=lak+now;now+=m*8+5;
    build_vtree();
    // cerr<<"SB"<<endl;
    fo(i,1,m){
        if(q[i].tp==0){
            lct.split(iid(q[i].x),iid(q[i].y));
            lct.pusht(iid(q[i].y),q[i].v);
        }
        else {
            lct.split(iid(q[i].x),iid(q[i].y));
            // cerr<<iid(q[i].y)<<endl;
            printf("%u\n",lct.sm[iid(q[i].y)]);
        }
    }
}
ui *tr1,*tr2;
void insert(ui x,ui v){
    for(int i=x;i<=n;i+=(i&-i)){
        tr1[i]+=v;tr2[i]+=v*(x-1);
    }
}
void ins(ui l,ui r,ui v){
    insert(l,v);insert(r+1,-v);
}
ui query(ui x){
    ui ret=0;
    for(int i=x;i;i-=(i&-i))ret+=tr1[i]*x-tr2[i];
    return ret;
}
ui qry(ui l,ui r){
    return query(r)-query(l-1);
}
void sol2(){
    tr1=fa;tr2=lak+now;now+=n+2;
    fo(i,0,n)tr1[i]=0;
    fo(i,1,n){
        a0=a0*a0*A+a0*B+C;
        ins(i,i,a0);
    }
    while(m--){
        ui tp,l,r,v;
        scanf("%u%u%u",&tp,&l,&r);
        if(l>r)swap(l,r);
        if(tp==0){
            scanf("%u",&v);
            ins(l,r,v);
        }
        else printf("%u\n",qry(l,r));
    }
}
ui Lca(int x,int y){
    while(x!=y){
        if(x<y)swap(x,y);
        x=fa[x];
    }return x;
}
void sol3(){
    a=lak+now;
    a[0]=a0;fo(i,1,n)a[i]=a[i-1]*a[i-1]*A+a[i-1]*B+C;
    while(m--){
        ui tp,l,r,v;
        scanf("%u%u%u",&tp,&l,&r);
        int lca=Lca(l,r);
        if(tp==0){
            scanf("%u",&v);
            while(l!=lca)a[l]+=v,l=fa[l];
            while(r!=lca)a[r]+=v,r=fa[r];
            a[lca]+=v;
        }
        else {
            int ans=0;
            while(l!=lca)ans+=a[l],l=fa[l];
            while(r!=lca)ans+=a[r],r=fa[r];
            ans+=a[lca];
            printf("%u\n",ans);
        }
    }
}
signed main(){
    freopen("problemprovidercreep.in","r",stdin);
    freopen("problemprovidercreep.out","w",stdout);
    // cerr<<(sizeof(lak)+sizeof(q)+sizeof(lct)>>20)<<endl;
    scanf("%u%u%u",&id,&n,&m);
    scanf("%u%u%u%u",&A,&B,&C,&a0);
    fa=lak;now+=n+5;
    fo(i,2,n)scanf("%u",&fa[i]);
    if(id==1)sol1();
    if(id==2)sol3();
    if(id==3)sol1();
    if(id==4)sol1();
    if(id==5)sol1();
    if(id==6)sol1();
    if(id==7)sol2();
    if(id==8)sol2();
    if(id==9)sol2();
    if(id==10)sol1();
    if(id==11)sol1();
    if(id==12)sol1();
    if(id==13)sol1();
    if(id==14)sol2();
    if(id==15)sol2();
    if(id==16)sol2();
    if(id==17)sol1();
    if(id==18)sol1();
    if(id==19)sol1();
    if(id==20)sol1();
    if(id==21)sol3();
    if(id==22)sol3();
    if(id==23)sol3();
    if(id==24)sol1();
    if(id==25)sol1();
    if(id==26)sol1();
    if(id==27)sol1();
    if(id==28)sol3();
    if(id==29)sol3();
    if(id==30)sol3();
    if(id==31)sol1();
    if(id==32)sol1();
    if(id==33)sol1();
    if(id==34)sol1();
    if(id==35)sol3();
    if(id==36)sol3();
    if(id==37)sol3();
    if(id==38)sol1();
    if(id==39)sol1();
    if(id==40)sol1();
    if(id==41)sol1();
    if(id==42)sol3();
    if(id==43)sol3();
    if(id==44)sol3();
    return 0;
}
posted @ 2022-06-08 14:34  fengwu2005  阅读(35)  评论(0编辑  收藏  举报