• Codeforces Round #668 (Div. 2)


    Codeforces Round #668 (Div. 2)

    A.Permutation Forgery

    题意:给一个数组p,找到另一个数组,使数组中相邻元素相加构成的新数组元素相同。
    思路:将数组反着输出。

    #pragma GCC optimize("Ofast")
    #pragma GCC target("avx,avx2,fma")
    #pragma GCC optimize ("unroll-loops")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<queue>
    #include<map>
    #include<stack>
    #include<iostream>
    #define INF 0x3f3f3f3f
    #define lowbit(a) ((a)&-(a))
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    ll t,n,a[1005]; 
    int main()
    {
    	scanf("%lld",&t);
    	while(t--)
    	{
    		cin>>n;
    		for(int i=1;i<=n;i++)
    		{
    			cin>>a[i];
    		} 
    		for(int i=n;i>=1;i--)
    		{
    			cout<<a[i]<<" ";
    		}
    		cout<<endl;
    	}	
    }
    

    B.Array Cancellation

    题意:给一个和为0的数组,每次可选择(a_i)-1和(a_j)+1,若i<j花费为0,否则花费为1,求所有数变为0的花费。
    思路:用num存所有数绝对值之和,sum存目前位置可用来与负数免费运算的值,ans存进行免费运算的值。因为每次都是2个数同时运算,所以答案为(num-ans$*$2)/2。

    #pragma GCC optimize("Ofast")
    #pragma GCC target("avx,avx2,fma")
    #pragma GCC optimize ("unroll-loops")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<queue>
    #include<map>
    #include<stack>
    #include<iostream>
    #define INF 0x3f3f3f3f
    #define lowbit(a) ((a)&-(a))
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    ll t,n,sum,a[100005],num,x,ans,s; 
    int main()
    {
    	scanf("%lld",&t);
    	while(t--)
    	{
    		sum=0;ans=0;x=0;num=0;
    		cin>>n;
    		for(int i=1;i<=n;i++)
    		{
    			cin>>a[i];
    			if(a[i]>0)
    			{
    				sum=sum+a[i];
    				num+=a[i];
    			}
    			if(sum>0&&a[i]<0)
    			{
    				num-=a[i];
    				s=-a[i];
    				x=min(sum,s);
    				sum=sum-x;
    				ans=ans+x;
    			}
    			else if(a[i]<0)
    			{
    				num-=a[i];
    			}
    		}
    		cout<<(num-2*ans)/2<<endl; 
    	}	
    }
    

    C.Balanced Bitstring

    题意:给一个二进制字符串,其中?能为0或1,问是否能使任意长度为k的字串0,1数量相同。
    思路:首先判断同余字符是否相同,不同则输出NO。用a[0]--a[k-1]存储同余位置的字符,若未确定(同余位置全是?)为0,若字符为'0'为1,若字符为'1'为2。再遍历一边字符串,若str[i]为'?',其同余数组a不为0,说明?可以确定,则?变为相应的字符串。遍历同余数组a,若没有a[i]为0,则判断为1和为2数量是否相同,相同YES,反之NO。若有a[i]为0,则为1和为2数量之差小于等于为数量,说明?肯定有一种分配可以使字符串0,1数量相等,则YES,反之则NO。

    #pragma GCC optimize("Ofast")
    #pragma GCC target("avx,avx2,fma")
    #pragma GCC optimize ("unroll-loops")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<queue>
    #include<map>
    #include<stack>
    #include<iostream>
    #define INF 0x3f3f3f3f
    #define lowbit(a) ((a)&-(a))
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    ll t,n,k,a[300005],flag,b[2],sum,len,sum1,sum2; 
    //string str;
    char str[300005];
    int main()
    {
    	scanf("%lld",&t);
    	while(t--)
    	{
    		memset(a,0,sizeof(a));
    		flag=0;
    		scanf("%lld%lld",&n,&k);
    		//cin>>str;
    		scanf("%s",str);
    		len=strlen(str);
    		for(int i=0;i<len;i++)
    		{
    			if(str[i]=='?')
    			{
    				continue;
    			}
    			else if(a[(i+1)%k]==0)
    			{
    				a[(i+1)%k]=str[i]-'0'+1;
    			}
    			else if(a[(i+1)%k]!=0)
    			{
    				if((str[i]-'0'+1)!=a[(i+1)%k])
    				{
    					flag=1;
    					printf("NO
    ");
    					break;
    				}
    			}
    		}
    		if(flag==0)
    		{
    		for(int i=0;i<len;i++)
    		{
    			if(str[i]=='?')
    			{
    				if(a[(i+1)%k]!=0)
    				{
    					str[i]=a[(i+1)%k]-1+'0';
    				}
    			}
    		}
    		sum=0;sum1=0;sum2=0;
    		for(int i=0;i<k;i++)
    		{
    			if(a[i]==0)
    			sum++;
    			if(a[i]==1)
    			sum1++;
    			if(a[i]==2)
    			sum2++;
    		}
    		if(sum)
    		{
    			if(abs(sum1-sum2)>sum)
    			{
    					flag=1;
    					printf("NO
    ");
    			}
    		}
    		else if(sum1!=sum2)
    		{
    					flag=1;
    					printf("NO
    ");
    		}
    		}
    		if(flag==0)
    		printf("YES
    ");
    	}	
    }
    

    D.Tree Tag

    题意:在一颗n个顶点的树上,Alice在a点,Bob在b点,Alice每次可走最多da步,Bob每次最多db步,Alice先走,若无限步内Alice和Bob可占据(每一步的起始,结束点为占据)同个点,Alice胜,反之Bob胜。
    思路:Alice获胜有3种可能。
    1.Alice一步抓到Bob,即da>(D_{ab}),用dfs计算ab距离 (D_{ab})
    2.2(*)da>(D_{tree}) ,即Alice站在树的直径中点可到达树的任何一点。用dfs1算出树的直径。
    3.db<2da,即BOb被Alice一直追到极限处,无法越过Alice反向逃跑。

    #pragma GCC optimize("Ofast")
    #pragma GCC target("avx,avx2,fma")
    #pragma GCC optimize ("unroll-loops")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<string>
    #include<queue>
    #include<map>
    #include<stack>
    #include<iostream>
    #define INF 0x3f3f3f3f
    #define lowbit(a) ((a)&-(a))
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    int t,n,a,b,da,db,ans,mmax,x,flag; 
    struct node
    {
    	int v;
    	int next;
    }s[200005];
    int first[400005],cnt,vis[200005];
    void init()
    {
    	memset(first,0,sizeof(first));
    	memset(vis,0,sizeof(vis));
    	cnt=1;flag=0;
    }
    void add(int u,int v)
    {
    	s[cnt].v=v;
    	s[cnt].next=first[u];
    	first[u]=cnt++;
    }
    void dfs(int u,int sum)//计算a,b间距离 
    {
    	vis[u]=1;
    	for(int i=first[u];i;i=s[i].next)
    	{
    		int v=s[i].v;
    		if(vis[v])
    		continue;
    		if(v==b)
    		{
    			ans=sum+1;
    			flag=1;
    			return;
    		}
    		dfs(v,sum+1);
    		if(flag==1)
    		return;
    	}
    }
    void dfs1(int u,int sum)
    {
    	vis[u]=1;
    	for(int i=first[u];i;i=s[i].next)
    	{
    		int v=s[i].v;
    		if(vis[v])
    		continue;
    		dfs1(v,sum+1);
    	}	
    	if(sum>mmax)
    	{
    		mmax=sum;
    		x=u;
    	}
    }
    int main()
    {
    	int u,v;
    	scanf("%d",&t);
    	while(t--)
    	{
    		cin>>n>>a>>b>>da>>db;
    		init();
    		for(int i=1;i<n;i++)
    		{
    			cin>>u>>v;
    			add(u,v);add(v,u);
    		}
    		ans=0;//记录a,b间距离 
    		dfs(a,0);
    		if(ans<=da)
    		{
    			cout<<"Alice"<<endl;
    			continue;
    		}
    		for(int i=1;i<=n;i++)
    		vis[i]=0;
    		mmax=0;
    		dfs1(1,0);//找到直径的一个端点 
    		for(int i=1;i<=n;i++)
    		vis[i]=0;
    		mmax=0;
    		dfs1(x,1);//算出直径的长度 
    		if(da<mmax/2&&db>da*2)
    		cout<<"Bob"<<endl;
    		else
    		cout<<"Alice"<<endl;
    	}	
    }
    

    E.Fixed Point Removal

    题意:给一个数列a,若a[i]==i则可以删除,删除后左右部分连接。询问q(x,y),前x个,后y个元素变为n+1,问每次询问能删几个数。
    思路:首先,进行转换a[i]=i-a[i];则a[i]的含义变为i位置左边若能删除a[i]个元素,则a[i]可以删除。
    若f(l,r)表示[l,r]区间最多能删除的数的个数,则(f[l][r]=f[l][r-1]+1(0<=a[r]<=f[l][r-1])),若a[i]不满足则(f[l][r]=f[l][r-1])。因为f(l,r)对于相同的r具有单调性,所以我们每次可以在树状数组上二分找点。(代码网上找的...)

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define maxn 300010
    
    int n,m,a[maxn];
    struct TREE{
    	int tr[maxn];
    	void add(int x){for(;x<=n;x+=(x&-x))tr[x]++;}
    	int sum(int x){int re=0;for(;x;x-=(x&-x))re+=tr[x];return re;}
    }tr;
    struct par{int x,pos;};
    vector<par>q[maxn];
    int ans[maxn];
    
    int main()
    {
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]=i-a[i];
    	for(int i=1,x,y;i<=m;i++)scanf("%d %d",&x,&y),q[n-y].push_back((par){1+x,i});
    	for(int i=1;i<=n;i++){
    		if(a[i]>=0){
    			int l=1,r=i,p=-1;
    			while(l<=r){
    				int mid=l+r>>1;
    				if(tr.sum(i)-tr.sum(mid-1)>=a[i])p=mid,l=mid+1;
    				else r=mid-1;
    			}
    			if(p!=-1)tr.add(p);
    		}
    		for(par j:q[i]){
    			ans[j.pos]=tr.sum(i)-tr.sum(j.x-1);
    		}
    	}
    	for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    网络数据包分析工具列表
    完美支持Py3的微信开发库推荐
    微信后台服务器地址验证的逻辑
    人工智能头条技能树图谱汇集
    如何构建通用 api 中间层
    vue 2.0 购物车小球抛物线
    基于Vue的事件响应式进度条组件
    vuex学习总结
    vue 上传图片到阿里云(前端直传:不推荐)
    vue-router的history模式发布配置
  • 原文地址:https://www.cnblogs.com/qingjielaojiu/p/13628960.html
Copyright © 2020-2023  润新知