B. Letters Shop

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

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

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

Educational Codeforces Round 67 (Rated for Div. 2)_预处理Educational Codeforces Round 67 (Rated for Div. 2)_预处理_02
#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\n",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  

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

Educational Codeforces Round 67 (Rated for Div. 2)_预处理Educational Codeforces Round 67 (Rated for Div. 2)_预处理_02
#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的数处理掉

Educational Codeforces Round 67 (Rated for Div. 2)_预处理Educational Codeforces Round 67 (Rated for Div. 2)_预处理_02
#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] )

Educational Codeforces Round 67 (Rated for Div. 2)_预处理Educational Codeforces Round 67 (Rated for Div. 2)_预处理_02
#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