zoukankan      html  css  js  c++  java
  • 十二省联考 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
    ",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
  • 相关阅读:
    教大家如何在word 2007中同时打出对齐上下标以及字母头上有波浪线(非编辑器)
    C#返回多个参数 ref及out
    回溯法解决0-1背包问题
    USB peripherals can turn against their users
    50元制作PS2键盘无线监控装置
    物联网安全拔“牙”实战——低功耗蓝牙(BLE)初探
    Bluetooth Low Energy 嗅探
    MagSpoof:能预测并窃取你下一张信用卡号码的廉价设备
    Python 安全类目推荐 (持续更新)
    树莓派安装kali后的简单配置
  • 原文地址:https://www.cnblogs.com/asd123www/p/10956572.html
Copyright © 2011-2022 走看看