省选模拟46

呵呵呵呵,我今天又一次被嘲讽了......一个月以内第三次被波波嘲讽eee

我菜,我菜废了,我菜到家了,啥也不会,啥也不是,完蛋玩意

今天的题确实是在考场上一点思路都没有,甚至板子一般的T1,没学过...

第二题可以看出和LCT有关,然而不会用,只想着能不能多骗几分

第三题确实想过树的计数,矩阵树定理嘛,然而想到是个森林就跑路了

T1 星际广播

二维dp显然,然而我自作聪明搞没了

发现这个非常的符合wqs二分的样子,有一个东西有最大的限制,并且是越多越优

还符合条件是个凸包,于是这个是wqs二分的板子,没想到吧

AC_code
#include<bits/stdc++.h>
using namespace std;
#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=1e6+5;
int n,m,ll,col[N];
char s[N];
int ans;
pair<int,double> dp[N];
bool jud(double c,int co){
    fo(i,1,n)dp[i]=make_pair(0,1e15);
    dp[0]=make_pair(0,0);
    fo(i,1,n){
        if(dp[i-1].second+(col[i]!=co)<=dp[i].second){
            dp[i]=dp[i-1];dp[i].second+=(col[i]!=co);
        }
        if(i>=ll){
            if(dp[i-ll].second+c<=dp[i].second){
                dp[i]=dp[i-ll];
                dp[i].first+=1;
                dp[i].second+=c;
            }
        }
    }
    return dp[n].first<=m;
}
int sol(int co){
    double l=0,r=1e3,mid;
    while(r-l>1e-8){
        mid=(l+r)/2;
        if(jud(mid,co))r=mid;
        else l=mid;
    }
    jud(l,co);
    return dp[n].second-l*m+0.5;
}
signed main(){
    freopen("radio.in","r",stdin);
    freopen("radio.out","w",stdout);
    n=read();m=read();ll=read();
    scanf("%s",s+1);
    fo(i,1,n){
        if(s[i]=='R')col[i]=0;
        else if(s[i]=='B')col[i]=1;
        else col[i]=2;
    }
    ans=min(sol(0),min(sol(1),sol(2)));
    printf("%d",ans);
    return 0;
}

T2 星际航道

发现一颗LCT可以维护边权不断变小的最小生成树,然后我祭了

考虑为什么给你一个网格图,很常见的对偶图

画出来之后发现,边集可以恰好划分成两个集合,一个是原图的最小生成树,一个是对偶图的最大生成树

于是我们就可以用两个LCT一个维护最小生成树,一个维护最大生成树

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll 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=1e5+5;
const int inf=0x3f3f3f3f;
int n,m,cid,q,typ;ll lstans;
void decode(char ch,int &x,int &y,int &w) {
    if(!typ)return ;
	static int mask = 0xfffff;
	w=(int)((w ^ lstans) & mask);
	if(ch=='-')x=(x+lstans-1)%n+1,y=(y+lstans-1)%(m-1)+1;
	if(ch=='|')x=(x+lstans-1)%(n-1)+1,y=(y+lstans-1)%m+1;
}
vector<int> id[N];
struct E{
    int x,y,w;
    bool operator < (E a)const{
        if(w!=a.w)return w<a.w;
        if(x!=a.x)return x<a.x;
        return y<a.y;
    }
}e[N*2],d[N*2];
int f[N*2];
bool com(int x,int y){
    if(e[x].w!=e[y].w)return e[x].w<e[y].w;
    if(e[x].x!=e[y].x)return e[x].x<e[y].x;
    return e[x].y<e[y].y;
}
int cie,bl[N*2];
map<pair<int,int>,int> mp;
struct LCTMIN{
    struct POT{
        int son[2],fa;
        int mx,ps,vl;bool rev;
    }tr[N*3];
    void init(){fo(i,0,cid)tr[i].vl=0;}
    void pushup(int x){
        tr[x].mx=max(tr[x].vl,max(tr[tr[x].son[0]].mx,tr[tr[x].son[1]].mx));
        if(tr[x].mx==tr[x].vl)tr[x].ps=x;
        else if(tr[x].mx==tr[tr[x].son[0]].mx)tr[x].ps=tr[tr[x].son[0]].ps;
        else tr[x].ps=tr[tr[x].son[1]].ps;
        return ;
    }
    void pushr(int x){
        swap(tr[x].son[0],tr[x].son[1]);
        tr[x].rev^=1;
    }
    void pushdown(int x){
        if(!tr[x].rev)return ;
        if(tr[x].son[0])pushr(tr[x].son[0]);
        if(tr[x].son[1])pushr(tr[x].son[1]);
        tr[x].rev=0;return ;
    }
    bool nroot(int x){return x==tr[tr[x].fa].son[0]||x==tr[tr[x].fa].son[1];}
    int get(int x){return x==tr[tr[x].fa].son[1];}
    void rotate(int x){
        int y=tr[x].fa,z=tr[y].fa;
        int 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[x].son[xpos^1]].fa=y;
        tr[x].son[xpos^1]=y;
        pushup(y);return ;
    }
    int pth[N],pt;
    void splay(int x){
        int now=x;pth[++pt]=now;
        while(nroot(now))pth[++pt]=now=tr[now].fa;
        while(pt)pushdown(pth[pt--]);
        while(nroot(x)){
            int y=tr[x].fa,z=tr[y].fa;
            int xpos=get(x),ypos=get(y);
            if(nroot(y)){
                if(xpos==ypos)rotate(y);
                else rotate(x);
            }rotate(x);
        }pushup(x);return ;
    }
    void access(int x){
        for(int y=0;x;y=x,x=tr[x].fa){
            splay(x);tr[x].son[1]=y;pushup(x);
        }
    }
    void makert(int x){
        access(x);splay(x);pushr(x);
    }
    int findrt(int x){
        access(x);splay(x);
        while(tr[x].son[0])pushdown(x),x=tr[x].son[0];
        splay(x);return x;
    }
    void split(int x,int y){
        makert(x);access(y);splay(y);
    }
    bool link(int x,int y){
        makert(x);
        if(findrt(y)==x)return false;
        tr[x].fa=y;return true;
    }
    bool lian(int x,int y,int z){
        return link(x,z)&&link(z,y);
    }
    bool cut(int x,int y){
        makert(x);
        if(findrt(y)!=x||tr[y].fa!=x||tr[y].son[0])return false;
        tr[x].son[1]=tr[y].fa=0;pushup(x);
        return true;
    }
    bool duan(int x,int y,int z){
        return cut(x,z)&&cut(z,y);
    }
    bool inone(int x,int y){
        return findrt(x)==findrt(y);
    }
    void change(int x,int v){
        makert(x);tr[x].vl=v;pushup(x);
    }
}lctmin;
struct LCTMAX{
    struct POT{
        int son[2],fa;
        int mx,ps,vl;bool rev;
    }tr[N*3];
    void init(){fo(i,0,cid)tr[i].vl=tr[i].mx=inf;}
    void pushup(int x){
        tr[x].mx=min(tr[x].vl,min(tr[tr[x].son[0]].mx,tr[tr[x].son[1]].mx));
        if(tr[x].mx==tr[x].vl)tr[x].ps=x;
        else if(tr[x].mx==tr[tr[x].son[0]].mx)tr[x].ps=tr[tr[x].son[0]].ps;
        else tr[x].ps=tr[tr[x].son[1]].ps;
        // if(tr[x].ps==0)cerr<<x<<" "<<tr[x].son[0]<<" "<<tr[x].son[1]<<" "<<tr[x].vl<<" "<<tr[x].mx<<endl;
        return ;
    }
    void pushr(int x){
        swap(tr[x].son[0],tr[x].son[1]);
        tr[x].rev^=1;
    }
    void pushdown(int x){
        if(!tr[x].rev)return ;
        if(tr[x].son[0])pushr(tr[x].son[0]);
        if(tr[x].son[1])pushr(tr[x].son[1]);
        tr[x].rev=0;return ;
    }
    bool nroot(int x){return x==tr[tr[x].fa].son[0]||x==tr[tr[x].fa].son[1];}
    int get(int x){return x==tr[tr[x].fa].son[1];}
    void rotate(int x){
        int y=tr[x].fa,z=tr[y].fa;
        int 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[x].son[xpos^1]].fa=y;
        tr[x].son[xpos^1]=y;
        pushup(y);return ;
    }
    int pth[N],pt;
    void splay(int x){
        int now=x;pth[++pt]=now;
        while(nroot(now))pth[++pt]=now=tr[now].fa;
        while(pt)pushdown(pth[pt--]);
        while(nroot(x)){
            int y=tr[x].fa,z=tr[y].fa;
            int xpos=get(x),ypos=get(y);
            if(nroot(y)){
                if(xpos==ypos)rotate(y);
                else rotate(x);
            }rotate(x);
        }pushup(x);return ;
    }
    void access(int x){
        for(int y=0;x;y=x,x=tr[x].fa){
            splay(x);tr[x].son[1]=y;pushup(x);
        }
    }
    void makert(int x){
        access(x);splay(x);pushr(x);
    }
    int findrt(int x){
        access(x);splay(x);
        while(tr[x].son[0])pushdown(x),x=tr[x].son[0];
        splay(x);return x;
    }
    void split(int x,int y){
        makert(x);access(y);splay(y);
    }
    bool link(int x,int y){
        makert(x);
        if(findrt(y)==x)return false;
        tr[x].fa=y;return true;
    }
    bool lian(int x,int y,int z){
        return link(x,z)&&link(z,y);
    }
    bool cut(int x,int y){
        makert(x);
        if(findrt(y)!=x||tr[y].fa!=x||tr[y].son[0])return false;
        tr[x].son[1]=tr[y].fa=0;pushup(x);
        return true;
    }
    bool duan(int x,int y,int z){
        return cut(x,z)&&cut(z,y);
    }
    bool inone(int x,int y){
        return findrt(x)==findrt(y);
    }
    void change(int x,int v){
        makert(x);tr[x].vl=v;pushup(x);
    }
}lctmax;
signed main(){
    freopen("channel.in","r",stdin);
    freopen("channel.out","w",stdout);
    typ=read();
    n=read();m=read();q=read();
    id[0].resize(m+2);
    fo(i,1,n){
        id[i].resize(m+2);
        fo(j,1,m)id[i][j]=++cid;
    }cid++;
    fo(i,0,m)id[0][i]=cid;
    fo(i,1,n)id[i][0]=cid;
    fo(i,1,n)fo(j,1,m){
        if(j+1<=m){
            mp[make_pair(id[i][j],id[i][j+1])]=++cie;
            e[cie]=E{id[i][j],id[i][j+1],0};
            int x=id[i][j],y=id[i-1][j];
            if(i==n)x=cid;if(x>y)swap(x,y);
            d[cie]=E{x,y,0};
        }
        if(i+1<=n){
            mp[make_pair(id[i][j],id[i+1][j])]=++cie;
            e[cie]=E{id[i][j],id[i+1][j],0};
            int x=id[i][j],y=id[i][j-1];
            if(j==m)x=cid;if(x>y)swap(x,y);
            d[cie]=E{x,y,0};
        }
    }
    lctmin.init();lctmax.init();
    fo(i,1,cie)f[i]=i;sort(f+1,f+cie+1,com);
    fo(i,1,cie){
        int x=f[i];
        if(lctmin.inone(e[x].x,e[x].y)){
            lctmax.lian(d[x].x,d[x].y,x+cid);
            bl[x]=1;
        }
        else {
            lctmin.lian(e[x].x,e[x].y,x+cid);
            bl[x]=0;
        }
    }
    while(q--){
        char tp[3];scanf("%s",tp+1);
        int x=read(),y=read(),w=read();
        decode(tp[1],x,y,w);int ide;
        if(tp[1]=='-')ide=mp[make_pair(id[x][y],id[x][y+1])];
        else ide=mp[make_pair(id[x][y],id[x+1][y])];
        if(w>=e[ide].w){
            if(bl[ide]==1){
                e[ide].w=d[ide].w=w;
                lctmin.change(ide+cid,w);
                lctmax.change(ide+cid,w);
            }
            else {
                lstans+=w-e[ide].w;
                e[ide].w=d[ide].w=w;
                lctmin.change(ide+cid,w);
                lctmax.change(ide+cid,w);
                lctmax.split(d[ide].x,d[ide].y);
                int mn=lctmax.tr[d[ide].y].mx,ps=lctmax.tr[d[ide].y].ps-cid;
                if(mn<w){
                    lctmax.duan(d[ps].x,d[ps].y,ps+cid);
                    lctmin.duan(e[ide].x,e[ide].y,ide+cid);
                    lctmax.lian(d[ide].x,d[ide].y,ide+cid);
                    lctmin.lian(e[ps].x,e[ps].y,ps+cid);
                    bl[ps]=0;bl[ide]=1;
                    lstans+=e[ps].w-e[ide].w;
                }
            }
        }
        else {
            if(bl[ide]==0){
                lstans+=w-e[ide].w;
                e[ide].w=d[ide].w=w;
                lctmin.change(ide+cid,w);
                lctmax.change(ide+cid,w);
            }
            else {
                // cerr<<"SB"<<endl;
                e[ide].w=d[ide].w=w;
                lctmin.change(ide+cid,w);
                lctmax.change(ide+cid,w);
                lctmin.split(e[ide].x,e[ide].y);
                int mx=lctmin.tr[e[ide].y].mx,ps=lctmin.tr[e[ide].y].ps-cid;
                if(mx>w){
                    lctmin.duan(e[ps].x,e[ps].y,ps+cid);
                    lctmax.duan(d[ide].x,d[ide].y,ide+cid);
                    lctmin.lian(e[ide].x,e[ide].y,ide+cid);
                    lctmax.lian(d[ps].x,d[ps].y,ps+cid);
                    bl[ide]=0;bl[ps]=1;
                    lstans+=e[ide].w-e[ps].w;
                }
            }
        }
        // fo(i,1,cie)cerr<<bl[i]<<" ";cerr<<endl;
        printf("%lld\n",lstans);
    }
}

T3 星际联邦

于是矩阵树定理,加入一个n+1节点将所有的树连起来,变成一颗整树

发现是个循环矩阵,于是可以直接用循环矩阵的公式求行列式,配个多项式,直接DFT

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=(1<<20)+5;
const int mod=998244353;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int n,k,ans;
int a[N],af[N],w[N],len,lim;
void ntt(int *a,int lim){
    fo(i,0,lim-1)if(af[i]>i)swap(a[i],a[af[i]]);
    for(int d=1,t=lim>>1;d<lim;d<<=1,t>>=1)
        for(int i=0;i<lim;i+=(d<<1))
            fo(j,0,d-1){
                int tmp=w[t*j]*a[i+j+d]%mod;
                a[i+j+d]=(a[i+j]-tmp+mod)%mod;
                a[i+j]=(a[i+j]+tmp)%mod;
            }
}
signed main(){
    freopen("federation.in","r",stdin);
    freopen("federation.out","w",stdout);
    len=k=read();lim=n=1<<k;
    fo(i,1,n-1)a[i]=mod-read(),a[0]=(a[0]+a[i])%mod;
    a[0]=(1+mod-a[0])%mod;
    // for(lim=1,len=0;lim<=n;lim<<=1,len++);
    fo(i,0,lim-1)af[i]=(af[i>>1]>>1)|((i&1)<<(len-1));
    w[0]=1;w[1]=ksm(3,(mod-1)/lim);
    fo(i,2,lim-1)w[i]=w[i-1]*w[1]%mod;
    ntt(a,lim);ans=1;
    fo(i,0,lim-1)ans=ans*a[i]%mod;
    printf("%lld\n",ans);
    return 0;
}
posted @ 2022-04-07 19:37  fengwu2005  阅读(53)  评论(0编辑  收藏  举报