十二省联考 2019

day1 T1:

异或之

注意scanf输入u32的方式

#include <bits/stdc++.h>
#define rep(a,b,i) for(int i=a;i<=b;++i)
#define per(a,b,i) for(int i=a;i>=b;--i)
using namespace std;
typedef long long s64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef pair<u32,int> pii;

const int M=5e5+5;
int n,m;
u32 a[M];
int rank_[M];

set <pii> q;

struct sp {
    sp *ch[2];
    int size;
}*root,*null;

void insert(sp *&g,u32 x,int c) {
    if(g==null) {
        g=new sp();
        g->size=0;
        g->ch[0]=g->ch[1]=null;
    }
    ++g->size;
    if(c==-1) return;

    insert(g->ch[x>>c&1],x,c-1);
}

u32 query(u32 x,int y) {
    u32 ans=0;
    sp *t=root;
    per(31,0,i) {
        bool c=(x>>i&1)^1;
        ans+=(u32)1<<i;
        if(t->ch[c]->size<y) ans-=(u32)1<<i,y-=t->ch[c]->size,c^=1;
        t=t->ch[c];
    }
    return ans;
}

u32 get_() {
    auto x=q.begin();
    u32 ans=-x->first;
    int p=x->second;
    q.erase(x);

    if(rank_[p]<n) ++rank_[p],q.insert((pii){-query(a[p],rank_[p]),p});

    return ans;
}


int main() {
    //freopen("a.in","r",stdin);

    scanf("%d%d",&n,&m);
    rep(1,n,i) scanf("%u",a+i),a[i]^=a[i-1];
    
    null=new sp();
    null->size=0;
    null->ch[0]=null->ch[1]=null;
    root=new sp();
    root->size=0;
    root->ch[0]=root->ch[1]=null;
    rep(0,n,i) insert(root,a[i],31);

    rep(0,n,i) rank_[i]=1,q.insert((pii){-query(a[i],1),i});

    s64 ans=0;
    rep(1,m,i) {
        u32 x=get_();get_();
        ans+=x;
    }
    cout<<ans<<endl;
}
day1 T1

 

day1 T2:

显然建图

后缀数组可以sort字符串后线段树优化,但是不好写

后缀自动机的fail树完全满足这个条件,只需要拆点就行了

#include <bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long s64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef pair<u32,int> pii;

const int M=1e6+5;

int len,n,m,t,x,y;
char s[M];
int las,cnt,mx[M],fa[M][20],nxt[M][26];

int l[M],r[M],q[M],du[M],val[M],pos[M];

s64 f[M];

vector <int> to[M],cc[M];

void extend_(int c) {
    int p=las,np=las=++cnt;
    mx[np]=mx[p]+1;
    while (p&&!nxt[p][c]) nxt[p][c]=np,p=fa[p][0];
    if(!p) fa[np][0]=1;
    else {
        int q=nxt[p][c];
        if(mx[q]==mx[p]+1) fa[np][0]=q;
        else {
            int nq=++cnt;
            fa[nq][0]=fa[q][0];
            memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
            mx[nq]=mx[p]+1,fa[q][0]=fa[np][0]=nq;
            while (nxt[p][c]==q) nxt[p][c]=nq,p=fa[p][0];
        }
    }
}

void dfs(int x) {
    rep(i,1,19) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(auto v:to[x]) dfs(v);
}


int find(int l,int r) {
    int ans=pos[r];
    per(i,19,0) if(mx[fa[ans][i]]>=r-l+1) ans=fa[ans][i];
    return ans;
}


bool check() {
    int h=1,tail_=0;
    memset(du,0,sizeof(du));
    rep(i,1,cnt+n) for(auto v:to[i]) ++du[v];
    rep(i,1,cnt+n) if(du[i]==0) q[++tail_]=i;

    while (h<=tail_) {
        int r=q[h++];
        for(auto v:to[r]) {
            --du[v];
            if(!du[v]) q[++tail_]=v;
        }
    }
    rep(i,1,cnt+n) if(du[i]) return 0;
    return 1;
}

int main() {
    //freopen("a.in","r",stdin);
    int test_;
    scanf("%d",&test_);

    while (test_--) {
        //init
        las=cnt=1;
        memset(fa,0,sizeof(fa));
        memset(nxt,0,sizeof(nxt));

        scanf("%s",s+1);
        len=strlen(s+1);
        per(i,len,1) extend_(s[i]-'a'),pos[len-i+1]=las;
        rep(i,1,cnt) if(fa[i][0]) to[fa[i][0]].push_back(i);
        dfs(1);
        rep(i,1,cnt) to[i].clear();



        scanf("%d",&n);
        rep(i,1,n) {
            scanf("%d%d",l+i,r+i);
            swap(l[i],r[i]);
            l[i]=len-l[i]+1,r[i]=len-r[i]+1;
            int x=find(l[i],r[i]);

            if(mx[x]!=r[i]-l[i]+1) cc[x].push_back(r[i]-l[i]+1);
        }


        scanf("%d",&m);
        rep(i,1,m) {
            scanf("%d%d",l+n+i,r+n+i);
            swap(l[n+i],r[n+i]);
            l[n+i]=len-l[n+i]+1,r[n+i]=len-r[n+i]+1;
        }
        scanf("%d",&t);
        rep(i,1,t) {
            scanf("%d%d",&x,&y);
            l[n+m+i]=x,r[n+m+i]=y;
            y+=n;
            x+=cnt+n;
            int c=find(l[y],r[y]);
            if(mx[fa[c][0]]+1!=r[y]-l[y]+1) cc[c].push_back(r[y]-l[y]);
        }

        rep(i,1,cnt) {
            sort(cc[i].begin(),cc[i].end());
            int pre=-1;
            for(auto v:cc[i]) {
                if(v==pre) continue;
                pre=v;
                ++cnt;
                fa[cnt][0]=fa[i][0];
                fa[i][0]=cnt;
                mx[cnt]=v;
            }
        }

        rep(i,1,cnt) if(fa[i][0]) to[fa[i][0]].push_back(i);
        dfs(1);


        rep(i,1,n) {
            int x=find(l[i],r[i]);
            if(mx[x]!=r[i]-l[i]+1) {
                cout<<mx[fa[x][0]]+1<<" "<<mx[x]<<" "<<r[i]-l[i]+1<<endl;
                cout<<"wrong!"<<endl;

                while (1);
            }
            to[x].push_back(cnt+i);
        }
        rep(i,1,t) {
            int x=l[n+m+i],y=r[n+m+i];
            int p=find(l[n+y],r[n+y]);
            to[cnt+x].push_back(p);
        }

        memset(val,0,sizeof(val));
        rep(i,1,n) val[cnt+i]=r[i]-l[i]+1;


        if(!check()) puts("-1");
        else {
            s64 ans=0;
            per(i,n+cnt,1) {
                int r=q[i];
                s64 Max=0;
                for(auto v:to[r]) Max=max(Max,f[v]);
                f[r]=val[r]+Max; 
                ans=max(ans,f[r]);
            }
            printf("%lld\n",ans);
        }
        rep(i,1,cnt+n) to[i].clear(),cc[i].clear();
    }
}
day1 T2

 

 

day2 T1:

最重要的思路就是$k=0$阵营和派系没有关系直接分开dp

$k>0$就直接dp这30个剩下按照$k=0$做就行了

#include <bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long s64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef pair<u32,int> pii;

const int M=2.5e3+5;
const int mod=998244353;

int n,m,K;
int C0,C1,D0,D1;
int A[2][2][M][305],B[2][2][M],C[2][M];


bool vis[M];

struct node {
    int s,p,b;

    bool operator <(const node &x) const {
        return b<x.b;
    }
}a[M];


inline void inc(int &x,int y) {x+=y,x-=x>=mod?mod:0;}

int main() {
    //freopen("a.in","r",stdin);
    int test_;
    scanf("%d",&test_);


    while (test_--) {
        memset(vis,0,sizeof(vis));

        int sum=0;
        scanf("%d%d",&n,&m);
        scanf("%d%d%d%d",&C0,&C1,&D0,&D1);
        rep(i,1,n) scanf("%d%d",&a[i].b,&a[i].s),a[i].p=-1,sum+=a[i].s;
        scanf("%d",&K);
        rep(i,1,K) {
            int x,y;
            scanf("%d%d",&x,&y);
            vis[a[x].b]=1,a[x].p=y;
        }

        sort(a+1,a+n+1);

        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        memset(C,0,sizeof(C));
        int opt[4]={0};

        A[0][0][0][0]=1;
        B[0][0][0]=1;
        C[0][0]=1;
        for(int l=1,r;l<=n;l=r+1) {

            r=l;
            while (a[r+1].b==a[r].b) ++r;

            rep(i,l,r) {
                if(a[i].p!=-1) continue;
                memset(C[opt[3]^1],0,sizeof(C[0]));
                rep(j,0,D0) if(C[opt[3]][j]) {
                    inc(C[opt[3]^1][j],C[opt[3]][j]);
                    if(j+a[i].s<=D0) inc(C[opt[3]^1][j+a[i].s],C[opt[3]][j]);
                }
                opt[3]^=1;
            }

            

            if(!vis[a[l].b]) {
                rep(i,l,r) {
                    memset(B[opt[2]^1],0,sizeof(B[0]));
                    rep(j,0,C0) {
                        //0
                        if(j>=a[i].s) {
                            inc(B[opt[2]^1][0][j],B[opt[2]][0][j-a[i].s]);
                            if(i==l) inc(B[opt[2]^1][0][j],B[opt[2]][1][j-a[i].s]);
                        }

                        //1
                        inc(B[opt[2]^1][1][j],B[opt[2]][1][j]);
                        if(i==l) inc(B[opt[2]^1][1][j],B[opt[2]][0][j]);
                    }
                    opt[2]^=1;
                }
            }
            else {
                int pre[2]={-1,0};
                rep(i,l,r) {
                    if(a[i].p!=-1) {
                        memset(A[opt[1]^1],0,sizeof(A[0]));
                        rep(j,0,C0) per(k,min(D0,300),0) {
                            int sum[2]={A[opt[1]][0][j][k],A[opt[1]][1][j][k]};
                            if(!sum[0]&&!sum[1]) continue;
                            rep(u,0,3) {
                                if(u==a[i].p) continue;
                                bool t0=u>>1,t1=u&1;
                                int x=j+(t0^1)*a[i].s,y=k+(t1^1)*a[i].s;
                                if(x<=C0&&y<=D0) {
                                    inc(A[opt[1]^1][t0][x][y],sum[t0]);
                                    if(pre[0]==-1) inc(A[opt[1]^1][t0][x][y],sum[t0^1]);
                                }
                            }
                        }
                        pre[0]=1;
                        opt[1]^=1;
                    }
                    else pre[1]+=a[i].s;
                }

                memset(A[opt[1]^1],0,sizeof(A[0]));
                per(j,C0,pre[1]) memcpy(A[opt[1]][0][j],A[opt[1]][0][j-pre[1]],sizeof(A[opt[1]][0][j]));
                per(j,pre[1],0)  memset(A[opt[1]][0][j],0,sizeof(A[opt[1]][0][j]));
            }
        }

        int ans=0;
        rep(i,0,C0) {
            inc(B[opt[2]][1][i],B[opt[2]][0][i]);
            if(i) inc(B[opt[2]][1][i],B[opt[2]][1][i-1]);
        }
        rep(i,1,D0) inc(C[opt[3]][i],C[opt[3]][i-1]);

        rep(i,0,1) rep(j,0,C0) per(k,min(300,D0),0) if(A[opt[1]][i][j][k]) {
            int c=A[opt[1]][i][j][k];
            int sel=B[opt[2]][1][C0-j];
            if(sum-j-C1>0) inc(sel,mod-B[opt[2]][1][sum-j-C1-1]);
            c=1ll*c*sel%mod;
            sel=C[opt[3]][D0-k];
            if(sum-k-D1>0) inc(sel,mod-C[opt[3]][sum-k-D1-1]);
            inc(ans,1ll*c*sel%mod);
        }
        cout<<ans<<endl;
    }
    //cout<<(double)clock()/CLOCKS_PER_SEC<<endl;
}
day2 T1

 

posted @ 2019-05-31 17:36  asd123www  阅读(498)  评论(2编辑  收藏  举报