zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 67 (Rated for Div. 2)

    B. Letters Shop

    给出一个母串和一些模式串

    求  最少取母串的前几个  使得模式串能完整的被这几个所表示

    预处理第几个字母的位置即可  

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=2e5+5;;
    int n,m,x,q;
     
    int a[200];
    char s[N],p[N];
     
    int cnt[200];
    int table[200][N];
    int ans;
    int main()
    {
        RI(n);RS(s+1);
        rep(i,1,n)
        {
            table[s[i]][++cnt[s[i]]]=i;
        }
        RI(m);
        rep(i,1,m)
        {
            RS(p+1);
            int lenp=strlen(p+1);
            rep(i,1,lenp)
            {
                a[ p[i] ]++;
            }
            ans=0;
            rep(i,'a','z')
            ans=max(ans,table[i][a[i]] ),a[i]=0;
            printf("%d
    ",ans);
        }
     
        return 0;
    }
    View Code

    C. Vasya And Array

    构造一个串   满足两个命令  

    命令1   l r 之间非递减

    命令0  l r   之间not 非递减

    比赛的时候  先处理命令1  将其做好标记  

    然后遍历所有的命令0  从左到右扫  如果能进行生成递减  那么可行   否则NO

    赛后果断被fst 了      错误也很显然  如果同样两段命令0   是不需要执行两次递减生成的 

    正确题解:

    如果保证 命令0为1 其他的所有位置都递减一下  这种串是最优串  然后遍历命令0来判断 yes or no

    有一个细节是  :

    如果遇到多个命令1  不需要每次从左到右开始扫  非常的慢(就是我第一次的做法QAQ)  正确的方式是  先进行左端排序   然后建立一个指针  遍历   为on!!!!!

    给出的是两两之间的关系   所以l - r 之间标记的 数目肯定是  l-r+1 -1  

    然后就可以处理出理想串了 

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    typedef pair<int,int>pii;
    //////////////////////////////////
    const int N=2e5+5;;
    int a[N],v[N],n,m,op,x,y;
    
    vector<pii>p,q;
    int main()
    {
        RII(n,m);
        rep(i,1,m)
        {
            RIII(op,x,y);
            if(op)p.pb({x,y});else q.pb({x,y});
        }
        sort(p.begin(),p.end());
        x=1;
        for(auto &i:p)
        {
            if(x<i.first)x=i.first;
            while(x<i.second)v[x++]=1;
        }
        int now=1;
        repp(i,n,1)
        if(v[i])a[i]=a[i+1];
        else a[i]=++now;
    
        for(auto &i:q)
        if(a[i.first]==a[i.second]){return puts("NO");}
        puts("YES");
        rep(i,1,n)printf("%d ",a[i]);
        return 0;
    }
    View Code

    D. Subarray Sorting

    给出两个数串 a b   问是否a能够通过多次操作 变为b

    操作: 每次选取区间 l r 进行sort 

    比赛的时候一千人过  赛后被fst的 只有一百个人也是第一次见

    题解:

    用线段树维护最小值 

    预处理每个数字的位置(包括第几个数字)

    然后遍历b  每次扫 1 到对应的数字的位置  如果这个区间的最小值小于b[i]那么  肯定是无解的   记得判断完之后将  线段树这个pos的数处理掉

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    typedef pair<int,int>pii;
    //////////////////////////////////
    const int N=2e6+10;
    #define lson l,m,pos<<1
    #define rson m+1,r,pos<<1|1
     
    int n,t[N<<2],m,cnt[N],x,b[N];
    map<pii,int>mp;
    void up(int pos){t[pos]=min(t[pos<<1],t[pos<<1|1]);}
    void update(int x,int v,int l,int r,int pos)
    {
        if(l==r){t[pos]=v;return;}
        int m=(l+r)>>1;
        if(x<=m)update(x,v,lson);
        else update(x,v,rson);
        up(pos);
    }
    int query(int L,int R,int l,int r,int pos)
    {
        int ans=inf;
        if(L<=l&&r<=R){return t[pos];}
        int m=(l+r)>>1;
        if(L<=m)ans=min(ans,query(L,R,lson));
        if(R>m)ans=min(ans,query(L,R,rson));
        return ans;
    }
    int sol()
    {
        RI(n);
        rep(i,1,n)t[i]=cnt[i]=0;
        rep(i,1,n)
        {
            RI(x);mp[{x,++cnt[x]}]=i;update(i,x,1,n,1);
        }
        rep(i,1,n)RI(b[i]),cnt[b[i]]--;
        rep(i,1,n)if(cnt[b[i]])return puts("NO");
        rep(i,1,n)
        {
            int p=mp[{b[i],++cnt[b[i]]}];
            if(query(1,p,1,n,1)<b[i])
                return puts("NO");
            update(p,n+1,1,n,1);
        }
        puts("YES");
    }
    int main()
    {
        int cas;RI(cas);
        while(cas--)sol();
        return 0;
    }
    View Code

    E. Tree Painting

    题意:给定一棵树  一开始所有的节点都是白色的   一开始选定一个点 将其涂黑  然后每次选定某个和黑色点相邻的点  将其染成黑色  

    每次的到的分数为  该选定点的所有联通的白点数量(包括选定这个点)

    题解:

    先选定一个root  为1  

    一遍dfs求出siz   显然  该点为一开始选定的点所得到的分数为  所有的siz 相加

    转化为相邻的点的 结果为  now + n - 2*siz[v]

    比如  当前点要向右边转移一步   那么  其所有左边的点(包括当前点的) 贡献全部加1  其右边的点的贡献全部-1     为  now+ 贡献左 - 贡献右   (贡献右为siz[v]   贡献左为 n-siz[v] )

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=2e6+10;
     
    int siz[N],n,m,b,pos,head[N];
    ll ans;
    struct Edge
    {
        int v,nex;
    }edge[N];
    void add(int a,int b)
    {
        edge[++pos]=Edge{b,head[a]};
        head[a]=pos;
    }
    void dfs(int u,int fa)
    {
        siz[u]=1;
        for(int i=head[u];i;i=edge[i].nex)if(edge[i].v!=fa)
        dfs(edge[i].v,u),siz[u]+=siz[edge[i].v];
    }
    void dfs1(int u,int fa,ll now)
    {
        ans=max(ans,now);
        for(int i=head[u];i;i=edge[i].nex)
        if(edge[i].v!=fa)
        dfs1(edge[i].v,u,now+n-2*siz[edge[i].v]);
    }
    int main()
    {
        RI(n);  
        rep(i,1,n-1)
        {
            int a,b;RII(a,b);
            add(a,b);add(b,a);
        }
        dfs(1,0);
        ll now=0;rep(i,1,n)now+=siz[i];
        dfs1(1,0,now);
        cout<<ans;
        return 0;
    }
    View Code
  • 相关阅读:
    牛牛的揠苗助长(二分)
    树型DP简单入门
    Rational Ratio(一道思维题)
    Tima goes to Xentopia(条件最短路)
    中国剩余定理
    求解逆元的三种方法
    samba 基本配置及自定义控制
    vue之虚拟DOM、diff算法
    vue-cli3构建ts项目
    VMware+node+nginx+vue
  • 原文地址:https://www.cnblogs.com/bxd123/p/11116520.html
Copyright © 2011-2022 走看看