zoukankan      html  css  js  c++  java
  • Educational Codeforces Round #67

    这一场的D题真的好惨烈.......FST了几百人qwq.........

    题目链接:戳我

    A Stickers and Toys

    一个egg里面有可能仅有toy,或者仅有sticker,或者两者都有.给你egg,toy,sticker的数量,你不知道具体每个egg里面的情况.现在问你最坏情况下至少要砸开多少个egg,才能获得至少一个toy和一个sticker.
    抽屉原理?没啥可说的.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define MAXN 200010
    using namespace std;
    int n,m,T,a,b;
     
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d%d",&n,&a,&b);
    		int ans=max(n-a+1,n-b+1);
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    

    B Letters Shop

    给你一个字符串s,然后以及若干询问(字符串t),问每次需要至少取s的多长前缀,重新组合之后可以拼成t.
    随便写一下就行了吧QAQ

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define MAXN 200010
    using namespace std;
    int n,m;
    int cnt[26],pos[26][MAXN],cur_cnt[26];
    char s[MAXN],cur[MAXN];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&n);
    	scanf("%s",s+1);
    	for(int i=1;i<=n;i++)
    	{
    		cnt[s[i]-'a']++;
    		pos[s[i]-'a'][cnt[s[i]-'a']]=i;
    	}
    	scanf("%d",&m);
    	for(int p=1;p<=m;p++)
    	{
    		scanf("%s",cur+1);
    		int len=strlen(cur+1),ans=0;
    		memset(cur_cnt,0,sizeof(cur_cnt));
    		for(int i=1;i<=len;i++)
    		{
    			cur_cnt[cur[i]-'a']++;
    			ans=max(ans,pos[cur[i]-'a'][cur_cnt[cur[i]-'a']]);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    C Vasya And Array

    给定你一些要求,t=1时,要求给定区间内的序列单调不降,t=0时,要求给定区间内的序列至少存在一组(a_i,a_j)满足(i<j)(a_i>a_j).让你构造序列.

    我们对整个序列做一个差分.先把单调不降的区间拉出来讨论,单调不降的话我们可以让他们相等.
    然后再处理t=0的情况.....我们可以选择区间内任意一个不需要和前面相等的数,使得他的差分值为-1.如果找不到这个数的话,那么就构造不出来这个序列了QAQ,返回false即可.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #define MAXN 200010
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,m;
    int a[MAXN],done[MAXN],ans[MAXN];
    struct Node{int op,l,r;}node[MAXN];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&node[i].op,&node[i].l,&node[i].r);
    	}
    	for(int i=2;i<=n;i++) a[i]=-inf;
    	for(int i=1;i<=m;i++)
    	{
    		if(node[i].op==0) continue;
    		for(int j=node[i].l+1;j<=node[i].r;j++) a[j]=0;
    	}
    	// for(int i=1;i<=n;i++) printf("%d ",a[i]); puts("");
    	for(int i=1;i<=m;i++)
    	{
    		if(node[i].op==1) continue;
    		bool flag=false;
    		for(int j=node[i].l+1;j<=node[i].r;j++)
    		{
    			if(a[j]==-1) 
    			{
    				flag=true;
    				break;
    			}
    			if(a[j]==-inf) 
    			{
    				a[j]=-1;
    				flag=true;
    				break;
    			}
    		}
    		if(flag==false)
    		{
    			cout<<"NO"<<endl;
    			return 0;
    		}
    	}
    	// for(int i=1;i<=n;i++) printf("%d ",a[i]); puts("");
    	cout<<"YES"<<endl;
    	for(int i=1;i<=n;i++) if(a[i]==-inf) a[i]=0;
    	for(int i=1;i<=n;i++)  ans[i]=ans[i-1]+a[i];
    	int minn=0;
    	for(int i=1;i<=n;i++) minn=min(minn,ans[i]);
    	for(int i=1;i<=n;i++) ans[i]+=-minn+1;
    	for(int i=1;i<=n;i++) printf("%d ",ans[i]); puts("");
    	return 0;
    }
    
    

    D Subarray Sorting

    最最惨烈的一道题,赛时看着好多人都过了.然后大量地FST.........

    给你两个序列,A和B,每次可以任意选定区间进行sort(排序默认从小到大),问能否从A操作成B.
    赛时想的思路是,只要两个序列里面的数都是一样的,因为大的肯定不能跑到小的前面,所以只要A的字典序大于B就行了.
    但是很容易被叉掉......比如说A=2 6 3 7,B=2 3 7 6

    考虑正解:
    我们对A建一个线段树,维护区间的最小值.
    然后我们考虑把B一个一个放进去,比如说当前处理的是B[i],这个数在A里面的出现位置为v.我们求[1,v]的最小值,如果最小值小于b[i],那么就不可能,返回false.否则我们更改v为一个很大的数(根据题意a[i],b[i]<=n,所以改成n+1即可)
    为什么这样子是对的?
    因为如果在放b[i]的时候,如果前面的最小值为a[j],它在B中的位置为k,那么显然j<->k的连线会与v<->i相交,而根据sort的原理,小的数是不能跑到大的数的后面的,所以不合法.我们修改完之后,相当于在这个位置已经确定可以放B的数了,所以改为n+1以免对后面的操作产生影响.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define MAXN 300010
    using namespace std;
    int n,T;
    int a[MAXN],b[MAXN],minn[MAXN<<2],cnt[MAXN];
    vector<int>pos[MAXN];
    inline int ls(int x){return x<<1;}
    inline int rs(int x){return x<<1|1;}
    inline void push_up(int x){minn[x]=min(minn[ls(x)],minn[rs(x)]);}
    inline void build(int x,int l,int r)
    {
        if(l==r) {minn[x]=a[l];return;}
        int mid=(l+r)>>1;
        build(ls(x),l,mid);
        build(rs(x),mid+1,r);
        push_up(x);
    }
    inline void update(int x,int l,int r,int pos,int k)
    {
        if(l==r) 
        {
            minn[x]=k;
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) update(ls(x),l,mid,pos,k);
        else update(rs(x),mid+1,r,pos,k);
        push_up(x);
    }
    inline int query(int x,int l,int r,int ll,int rr)
    {
        if(ll<=l&&r<=rr) return minn[x];
        int mid=(l+r)>>1,cur_ans=0x3f3f3f3f;
        if(ll<=mid) cur_ans=min(cur_ans,query(ls(x),l,mid,ll,rr));
        if(mid<rr) cur_ans=min(cur_ans,query(rs(x),mid+1,r,ll,rr));
        return cur_ans;
    }
    inline bool solve()
    {
        for(int i=1;i<=n;i++)
        {
            int siz=(int)pos[b[i]].size();
            if(siz<=cnt[b[i]]) return false;
            int now=pos[b[i]][cnt[b[i]]++];
            if(query(1,1,n,1,now)<b[i]) return false;
            update(1,1,n,now,n+1);
        }
        return true;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++) pos[i].clear(),cnt[i]=0;
            for(int i=1;i<=n;i++) 
            {
                scanf("%d",&a[i]);
                pos[a[i]].push_back(i);
            }
            for(int i=1;i<=n;i++) scanf("%d",&b[i]);
            build(1,1,n);
            if(solve()==true) printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }
    

    E Tree Painting

    简化版题意:任意选取一个点为根,求最大的子树大小和.
    感觉有点像换根DP,先来一遍dfs求出来以(比如说1)为根的子树大小和,然后你再来一个dfs换根,就好了

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define MAXN 200010
    using namespace std;
    int n,t;
    int head[MAXN],siz[MAXN];
    long long ans;
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline void add(int from,int to)
    {
        edge[++t].nxt=head[from],edge[t].to=to;
        head[from]=t;
    }
    inline void dfs(int x,int pre)
    {
        siz[x]=1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==pre) continue;
            dfs(v,x);
            siz[x]+=siz[v];
            // printf("[%d %d] %d
    ",x,v,siz[x]);
        }
    }
    inline void change_root(int x,int pre,long long w)
    {
        ans=max(ans,w);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(v==pre) continue;
            change_root(v,x,(w-siz[v])+(n-siz[v]));
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        dfs(1,0);
        // for(int i=1;i<=n;i++)
            // printf("siz[%d]=%d
    ",i,siz[i]);
        for(int i=1;i<=n;i++) ans+=siz[i];
        // printf("ans=%lld
    ",ans);
        change_root(1,0,ans);
        printf("%lld
    ",ans);
        return 0;
    }
    

    然后后面的题本菜鸡还不会写.........
    先咕着吧.......

    (唔,最后感谢一下赛时给我提供题意BLUESKY007神仙qwq)

  • 相关阅读:
    算法笔记 第11章 提高篇(5) --动态规划专题 学习笔记
    算法笔记 上机训练实战指南 第10章 提高篇(4)--图算法专题 学习笔记
    算法笔记 第10章 提高篇(4) --图算法专题 学习笔记
    算法笔记 上机训练实战指南 第9章 提高篇(3)--数据结构专题(2) 学习笔记
    算法笔记 第9章 提高篇(3) --数据结构专题(2) 学习笔记
    算法笔记 上机训练实战指南 第8章 提高篇(2)--搜索专题 学习笔记
    算法笔记 第8章 提高篇(2) --搜索问题 学习笔记
    算法笔记 上机训练实战指南 第7章 提高篇(1)--数据结构专题(1) 学习笔记
    算法笔记 上机训练实战指南 第6章 C++标准模板库(STL)介绍 学习笔记
    算法笔记 上机训练实战指南 第5章 入门篇(3) --数学问题 学习笔记
  • 原文地址:https://www.cnblogs.com/fengxunling/p/11119382.html
Copyright © 2011-2022 走看看