zoukankan      html  css  js  c++  java
  • The Preliminary Contest for ICPC Asia Xuzhou 2019

    B.so easy

    并查集,可能会卡掉map,建议使用unordered_map。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6+100;
    const int mod = 1e9+7;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const ll llINF = 0x3f3f3f3f3f3f3f3f;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fep(i,a,b) for(int i=(a);i>=(b);i--)
    inline bool read(ll &num) {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        } 
        if(IsN) num=-num;
        return true;
    }
    unordered_map<int,int> par;
    int find(int x){
        if(par[x]==0){
            par[x]=x;
            return x;
        }
        return x==par[x]?x:par[x]=find(par[x]);
    }
    int main(){
        int n,q;
        scanf("%d %d",&n,&q);
        int op,x;
        while(q--){
            scanf("%d %d",&op,&x);
            if(op==1){
                par[find(x)]=x+1;
            }else{
                if(find(x)>n) puts("-1");
                else printf("%d
    ",find(x));
            }
        }
        return 0;
    }
    

    C.Buy Watermelon

    签到,大于2的偶数都可以被拆分成两个偶数和。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6+100;
    const int mod = 1e9+7;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const ll llINF = 0x3f3f3f3f3f3f3f3f;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fep(i,a,b) for(int i=(a);i>=(b);i--)
    inline bool read(ll &num) {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        } 
        if(IsN) num=-num;
        return true;
    }
    int main(){
      //  freopen("1.in", "r", stdin);
        ll t,n;
        read(n);
        if(n>2&&(n%2==0)){
            cout<<"YES"<<endl;
        }
        else{
            cout<<"NO"<<endl;
        }
        return 0;
    }
    

    D. Carneginon

    KMP,懒得写了(狗头)。。

    E. XKC's basketball team

    对于每个(i)查找最右的大于等于(a_i+m)的位置。线段树维护区间最大值优先查右子树即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e6+100;
    const int mod = 1e9+7;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const ll llINF = 0x3f3f3f3f3f3f3f3f;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fep(i,a,b) for(int i=(a);i>=(b);i--)
    inline bool read(ll &num) {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        } 
        if(IsN) num=-num;
        return true;
    }
    int mxx[N],a[N];
    int n,m;
    void pushup(int rt){
        mxx[rt]=max(mxx[rt<<1],mxx[rt<<1|1]);
    }
    void buildtree(int rt,int l,int r){
        mxx[rt]=0;
        if(l==r){
            mxx[rt]=a[l];return ;
        }
        int mid=(l+r)>>1;
        buildtree(rt<<1,l,mid);
        buildtree(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    int query(int rt,int l,int r,int x){
       // cout<<rt<<' '<<l<<' '<<r<<' '<<mxx[rt]<<endl;
        if(l==r){
            if(mxx[rt]>=x){
                 return l;
            }
            else return -1;
        }
        int mid=(l+r)>>1;
        if(mxx[rt<<1|1]>=x){
            return query(rt<<1|1,mid+1,r,x);//先查右面
        }else{
            return query(rt<<1,l,mid,x);
        }
    }
    int main(){
        //freopen("1.in", "r", stdin);
        scanf("%d %d",&n,&m);
        rep(i,1,n) scanf("%d",&a[i]);
        buildtree(1,1,n);
        vector<int> ans;
        rep(i,1,n){
            int id=query(1,1,n,a[i]+m);
            if(id<=i) ans.push_back(-1);
            else{
                ans.push_back(id-i-1);
            }
        }
        printf("%d",ans[0]);
        rep(i,1,(int)ans.size()-1) printf(" %d",ans[i]);
        puts("");
        return 0;
    }
    

    I. query

    对于([1,n]),枚举它们所有的倍数,总对数也就大概只有(O(n cdot log(n))),因此转化为一个正方形,每次查询([l,l])([r,r])之间点的个数即可。接下来直接离线然后用树状数组维护前缀和即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e6+100;
    const int mod = 1e9+7;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const ll llINF = 0x3f3f3f3f3f3f3f3f;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fep(i,a,b) for(int i=(a);i>=(b);i--)
    inline bool read(ll &num) {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        } 
        if(IsN) num=-num;
        return true;
    }
    
    int n,m;
    int c[N];
    int lowbit(ll x){
        return (x&(-x));
    }
    void add(ll x,ll v){
        for(;x<N;x+=lowbit(x)){
             c[x]+=v;
             //cout<<x<<' '<<v<<endl;
        }
    }
    ll query(ll x){
        ll ans=0;
        for(;x;x-=lowbit(x)){
            ans+=c[x];
        }
        return ans;
    }
    
    int pos[N],a[N];
    int l[N],r[N];
    struct point{
        int x,y,flag;
    }s[N];
    bool cmp(point a,point b){
        if(a.x==b.x){
            if(a.y==b.y){
               return a.flag<b.flag;
            }
            return a.y<b.y;
        }
        return a.x<b.x;
    }
    int yy[N],id[N];
    map<pair<int,int>,int> mmp;
    
    int main(){
        scanf("%d %d",&n,&m);
        rep(i,1,n){
             scanf("%d",&a[i]);
             pos[a[i]]=i;
        }
        int cnt=0;
        rep(i,1,n){
            for(int j=2*i;j<=n;j+=i){
                s[++cnt]={pos[i],pos[j],0};
            }
        }
        rep(i,1,m){
            scanf("%d %d",&l[i],&r[i]);
            s[++cnt]={r[i],r[i],1};
            s[++cnt]={l[i]-1,r[i],1};
            s[++cnt]={r[i],l[i]-1,1};
            s[++cnt]={l[i]-1,l[i]-1,1};
        }
    
        rep(i,1,cnt) yy[i]=s[i].y;
    
        sort(yy+1,yy+cnt+1);
        int siz=unique(yy+1,yy+cnt+1)-yy-1;
    
        sort(s+1,s+cnt+1,cmp);
        rep(i,1,cnt){
            id[i]=lower_bound(yy+1,yy+siz+1,s[i].y)-yy;
        }
        rep(i,1,cnt){
            if(s[i].flag==0){
                add(id[i],1);
            }else{
                mmp[{s[i].x,s[i].y}]=query(id[i]);
            }
        }
        rep(i,1,m){
            printf("%d
    ",mmp[{r[i],r[i]}]-mmp[{l[i]-1,r[i]}]-mmp[{r[i],l[i]-1}]+mmp[{l[i]-1,l[i]-1}]);
        }
        return 0;
    }
    

    J. Random Access Iterator

    首先预处理出每个点所能到达的最大深度和子节点的数量,令(dp[x])表示能到达叶子节点的概率,当从(u)(v)转移时,只有(v)能到达的的最大深度等于树的深度时才能转移。对于叶子节点:(dp[x]=1),向上转移即可。

    [dp[u]=1-(1- frac{sum{dp[v]}}{|siz[u]|})^{|siz[u]|} ]

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6+100;
    const int mod = 1e9+7;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const ll llINF = 0x3f3f3f3f3f3f3f3f;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fep(i,a,b) for(int i=(a);i>=(b);i--)
    inline bool read(ll &num) {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        } 
        if(IsN) num=-num;
        return true;
    }
    ll qpow(ll a,ll b){
        ll ans=1;
        while(b){
            if(b&1) ans=(ans%mod*a%mod)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans%mod;
    }
    ll inv(ll a){
        return qpow(a,mod-2);
    }
    vector<int> G[N];
    int depth[N],maxxh[N],siz[N];
    void dfs(int u,int par){
        depth[u]=depth[par]+1;
        maxxh[u]=depth[u];
        for(int v:G[u]){
            if(v==par) continue;
            siz[u]++;
            dfs(v,u);
            maxxh[u]=max(maxxh[u],maxxh[v]);
        }
    }
    ll dp[N];
    ll solve(ll u,ll fa){
        if(siz[u]==0) return dp[u]=1;
        ll ans=0;
        for(int v:G[u]){
            if(v==fa) continue;
            if(maxxh[v]==maxxh[1]){
                ans+=solve(v,u);
            }
        }
        ans=ans*inv(siz[u])%mod;
        return dp[u]=(1-qpow(1-ans+mod,siz[u])+mod)%mod;
    }
    int main(){
        int n,u,v;
        cin>>n;
        rep(i,1,n-1){
            cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,1);
        cout<<solve(1,1)<<endl;
        return 0;
    }
    

    M. Longest subsequence

    (S)中找到最长的子序列使其字典序大于(T),输出长度即可。

    假设子序列为(T'),如果(T'>T),则(T')一定存在某个位置(p)使得(T'[1...p-1]=T[1...p]),而(T'[p]>T[p]),枚举(p),利用序列自动机计枚举(T'[p])并快速求的位置,计算答案即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6+100;
    const int mod = 1e9+7;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const ll llINF = 0x3f3f3f3f3f3f3f3f;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define fep(i,a,b) for(int i=(a);i>=(b);i--)
    inline bool read(ll &num) {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        } 
        if(IsN) num=-num;
        return true;
    }
    int nxt[N][27];
    void init(char *s){
        int l=strlen(s);
        for(int i=0;i<26;i++) nxt[l][i]=INF;
        for(int i=l-1;i>=0;i--){
            for(int j=0;j<26;j++){
                nxt[i][j]=nxt[i+1][j];
            }
            nxt[i][s[i]-'a']=i;
        }
    }
    char s[N],t[N];
    int main(){
        //freopen("1.in", "r", stdin);
        int n,m;
        cin>>n>>m;
        scanf("%s %s",s,t);
        init(s);
        int pos=-1;
        int ans=0;
        int cnt=0;
        bool flag=0;
        vector<int> id;
        for(int i=0;i<n;i++){
            for(int j=t[cnt]-'a'+1;j<26;j++){
                if(nxt[i][j]!=INF){
                    flag=1;
                    ans=max(ans,cnt+n-nxt[i][j]);
                }
            }
            if(s[i]==t[cnt]){
                cnt++;
                id.push_back(i);
            }
            if(cnt==m) break;
        }
        if(!flag){
            if(id.size()==m){
                if(id[m-1]==n-1)cout<<-1<<endl;
                else cout<<m+(n-id[m-1]-1)<<endl;
            }
            else cout<<-1<<endl;
        }
        else{
            if(id.size()==m&&id[m-1]!=-1){
                ans=max(ans,m+(n-id[m-1]-1));
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    2019.01.06-dtoj-2437: [Noi2011]兔兔与蛋蛋
    2019.01.03-bzoj-1443-[JSOI2009]游戏Game
    2019.01.03-dtoj-4104-yjqaa
    2019.01.03-sg函数模板
    2019.01.02-bzoj-4550: 小奇的博弈
    2019.01.02-dtoj2293-幻想乡开店(shop)
    OCP 071中文考试题库(cuug内部资料)第5题
    OCP 063中文考试题库(cuug内部资料)第4题
    OCP 063中文考试题库(cuug内部资料)第3题
    OCP 062中文考试题库(cuug内部资料)第4题
  • 原文地址:https://www.cnblogs.com/codancer/p/12232412.html
Copyright © 2011-2022 走看看