Codeforces Round #627 (Div. 3)

Codeforces Round #627 (Div. 3)

难道这会是我第一场能补完题的cf场?虽然是div3

A. Yet Another Tetris Problem

题意

给一个俄罗斯方块的残局,每次可以放一个高2宽1的块,问能否全部消除

题解

检测一下所有数的奇偶性,全部相同就可以消除
ps:题意懂了就是手速题

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{   long _,n,i,x,a1,a0;
    for(scanf("%ld",&_);_;_--){
        scanf("%ld",&n);
        a0=a1=0;
        for(i=1;i<=n;i++){
            scanf("%ld",&x);
            if(x%2)a1++;
            else a0++;
        }
        if(a1==n||a0==n)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

B. Yet Another Palindrome Problem

题意

给一串数字,求能否构成长度不小于3的回文串,取的数可以不连续但是相对顺序不可变

题解

因为可以不连续,只要找有两位相等的而且不相邻就好了
ps:又是手速题

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define def 5010
using namespace std;

long a[def];

int main()
{   long _,n,i,j;
    for(scanf("%ld",&_);_;_--){
    	scanf("%ld",&n);
    	for(i=1;i<=n;i++)
    		scanf("%ld",&a[i]);
    	bool t=false;
    	for(i=1;i<=n;i++)
    		for(j=i+2;j<=n;j++)
    			if(a[i]==a[j]){
    				t=true;
    				break;
    			}
    	if(t)
    		printf("YES\n");
    	else
    		printf("NO\n");
    }
    return 0;
}

C. Frog Jumps

题意

青蛙过河,河中每个石子有自己的属性L和R,L只能向左跳,R只能向右跳,每次最多跳\(k\)步,求能过河的最小的\(k\)

题解

只要保证每次都能跳到R就能过河,所以最小值就是\(max\){起点到第一个R的距离,最后一个R到终点的距离,max{两个R之间的距离}}
ps:刚开始有了思维定势,直接去想二分了,还好后来改了回来

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define max(a,b) (((a)>(b))?(a):(b))
using namespace std;

int main()
{   long _,ans,i;
    string s;
    for(scanf("%ld",&_);_;_--){
        cin>>s;
        s='R'+s+'R';
        ans=0;
        for(i=0;i<s.length()-1;i++)
            if(s[i]=='R')
                ans=max(ans,s.find("R",i+1)-i);
        printf("%ld\n",ans);
    }
    return 0;
}

D. Pair of Topics

题意

给出两个数列,找出满足\(a_i+a_j>b_i+b_j (i<j)\)的对数

题解

移项,\(a_i-b_i>b_j-a_j(i<j)\),这样就变成了\(c_i>-c_j(i<j)\)
这样问题变成了:计算某个数之前有几个数比他的相反数小,典型的离散化+树状数组
ps:开局直接开了D,还好不难,心态没崩,不过好像我的方法不是最简单的?

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#define ll long long
#define lowbit(i) ((i)&0-(i))
#define def 400010
using namespace std;

map<ll,long>mp;
long sum[def];
ll a[def],b[def];

//树状数组
void add(long x,long y)
{
    for(;x<def;x+=lowbit(x))
        sum[x]+=y;
}

long query(long x)
{   long ans=0;
    for(;x;x-=lowbit(x))
        ans+=sum[x];
    return ans;
}

int main()
{   long n,i,cnt=0;
    ll ans=0,x;
    scanf("%ld",&n);
    for(i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    for(i=1;i<=n;i++){
        scanf("%lld",&x);
        a[i]-=x;
    }
    //离散化
    for(i=1;i<=n;i++){
        b[i]=a[i];
        b[i+n]=-a[i];
    }
    sort(b+1,b+2*n+1);
    b[2*n+1]=b[2*n]+1;
    for(i=1;i<=2*n;i++)
        if(b[i]!=b[i+1])
            mp[b[i]]=++cnt;
    //统计
    for(i=1;i<=n;i++){
        ans+=i-1-query(mp[-a[i]]);
        add(mp[a[i]],1);
    }
    printf("%lld\n",ans);
    return 0;
}

E. Sleeping Schedule

题意

一个人睡觉一次睡一天,第\(i\)次醒来后\(a_i\)或者\((a_i-1)\)小时后才会再次睡觉,每天有\(h\)小时,其中在\([l,r]\)小时区间内睡着就是一个“好睡眠”,从第1天的0时开始醒来,求最多能得到的“好睡眠”数

题解

n是2000,h是2000,很容易想对他们动心思,然后就想到了二维dp,用\(f_{i,j}\)表示第i-1次在第j小时醒来,到最后能得到的最多“好睡眠”数,方程挺好写的,具体实现见代码
ps:比赛时wa40我也是第一次见,后来发现忘了特判第一天QAQ

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define def 2010
using namespace std;

long long a[def],f[def][def];

int main()
{	long long n,h,l,r,i,j;
	scanf("%lld%lld%lld%lld",&n,&h,&l,&r);
	for(i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(i=l;i<=r;i++)
		f[n+1][i]=1;
	for(i=n;i>=1;i--)
		for(j=0;j<h;j++){
			f[i][j]=max(f[i+1][(j+a[i])%h],f[i+1][(j+a[i]-1+h)%h]);
			if(l<=j&&j<=r&&i!=1)
				f[i][j]++;
		}
	printf("%lld\n",f[1][0]);
	return 0;
}

F. Maximum White Subtree

10:30 我去补题,这次一定不咕
11:36 没咕没咕

题意

给出一颗无根树,每个点有一个颜色(黑/白),求每个点的包含他的子树中,黑白点数差值最大多少

题解

首先指定一个根,比如1为根,然后求出每个点为根的子树里黑白点数最大差值
接着进行一次dp,算出每个点作为根节点时的黑白最大差值
现在的重点是dp时的转移,上边已经求出了\(f_i\)表示以i为根的子树的黑白最大差,那么以i为根节点的黑白最大差\(ans_i=max(ans_{fa}-max(f_i,0),0)+f_i\)
ps:英文不好,理解错题,耽搁了QAQ

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define def 200010
using namespace std;

vector<long>mp[def];
long fa[def],f[def],ans[def],a[def];

long max(long a,long b)
{
	return a>b?a:b;
}

long dfs(long now)
{	long sum=0;
	for(auto next:mp[now])
		if(next!=fa[now]){
			fa[next]=now;
			f[next]=dfs(next);
			sum+=max(f[next],0);
		}
	return sum+a[now];
}

void dp(long now)
{
	ans[now]=max(ans[fa[now]]-max(f[now],0),0)+f[now];
	for(auto next:mp[now])
		if(next!=fa[now])
			dp(next);
}

int main()
{	long n,i,x,y,minn,sum;
	scanf("%ld",&n);
	for(i=1;i<=n;i++){
		scanf("%ld",&a[i]);
		a[i]=a[i]?1:-1;
	}
	for(i=1;i<n;i++){
		scanf("%ld%ld",&x,&y);
		mp[x].push_back(y);
		mp[y].push_back(x);
	}
	fa[1]=0;
	f[1]=dfs(1);
	dp(1);
	for(i=1;i<=n;i++)
		printf("%ld ",ans[i]);
	printf("\n");
	return 0;
}

_______________________________________________
终于有一次赛后ak的了,红红火火恍恍惚惚

posted @ 2020-03-13 10:27  dreaming2019  阅读(204)  评论(0编辑  收藏  举报