Codeforces Round #627 (Div. 3) A-E(题解)

在virtual一顿操作猛如虎,一到实战就拉跨. 这场div3的A-E都不是很难,手速场.F看了一眼大概是树形dp的题,不熟练,先放着以后来补坑.
A Yet Another Tetris Problem
题目大意:玩俄罗斯方块,只不过只有1×2的方块.给一个初始状况问能不能All Clear.
最简单的方法.减掉最小值.看最后有没有奇数块,没有的话就可以.
代码

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
 
int a[N];
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		bool f = 0;
		int mx = 1e9;
		fir(i,1,n){
			cin >> a[i];
			mx = min(mx,a[i]);
		}
		fir(i,1,n){
			a[i] -= mx;
			if(a[i] % 2 != 0){
				f = 1;
				break;
			}
		}
		if(f) puts("NO");
		else puts("YES");
	}
	
	return 0;
}

B - Yet Another Palindrome Problem
题目大意:给一个数组,找有没有长度为3的回文子序列.
唯一的WA贡献给了它.暴力可能会超时吧(没试过).长度为3其实很简单找.只要有两个数一样并且距离>1就可以了.要注意一下存每个数第一次出现的位置就好了.不要急躁,不然就会WA.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 5e3+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int a[N],vis[N];
int main(){
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		fir(i,1,n) vis[i] = 0;
		bool f = 0;
		fir(i,1,n){
			cin >> a[i];
			if(vis[a[i]] && i-vis[a[i]] > 1) f = 1;
			if(!vis[a[i]]) vis[a[i]] = i;
		}
		if(f) puts("YES");
		else puts("NO");
	}
	
	return 0;
}

C - Frog Jumps
题目大意:给一个字符串只有L和R.代表在这个位置能向左跳或者向右跳最多跳x距离.求能达到终点的最小x.
用学长的话来说,这是一眼二分题.显然L是没用的.而且答案具有单调性.二分check一下就好了.每次尽量往右跳.简单的证明一下.往左跳并不会使你的选择区间变大.只会变小.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
string s;
bool check(int len){
	int mx = 1,last = -1;
	fir(i,0,(int)s.size()-1){
		if(s[i] == 'R'){
			mx = max(mx,i-last);
			last = i;
		}
	}
	mx = max(mx,(int)s.size()-last);
	if(mx > len) return false;
	return true;
}
int main(){
	int t;
	cin >> t;
	while(t--){
		cin >> s;
		int l = 1,r = (int)s.size()+1;
		while(l<r){
			int mid = l+r>>1;
			if(check(mid)){
				r = mid;
			}
			else{
				l = mid+1;
			}
		}
		cout << l << endl;
	}
	
	return 0;
}

D - Pair of Topics
题目大意:直接看题目吧.没啥花里胡哨的
观察一下给的结构 ai+aj > bi+bj. 移动一下 ai-bi >bj-aj. (i>j) 这样子题目就变成了. j这个位置前面有多少个ai-bi >bj-aj. 这个问题可以拿一个树状数组或者线段树做.我用的是树状数组.知识点传送门.学了下次一定会做系列.对权值建树就OK了.不过要离散化一下.

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e5+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int a[N],b[N],c[N*4],tn;
vi all;
int get(int x){
	return lower_bound(ALL(all),x)-all.begin();
}
int ask(int x){
	int res = 0;
	for(;x;x-=x&-x) res += c[x];
	return res;
}
void add(int x){
	for(;x<=tn;x+=x&-x) c[x] += 1;
}
int main(){
	int n;
	cin >> n;
	all.pb(-2e9-20);
	fir(i,1,n){
		cin >> a[i];
	}
	fir(i,1,n){
		cin >> b[i];
		all.pb(a[i]-b[i]);
		all.pb(b[i]-a[i]);
	}
	sort(ALL(all));
	all.erase(unique(ALL(all)),all.end());
	tn = all.size();
	LL ans = 0;
	fir(i,1,n){
		int c1 = get(b[i] - a[i]),c2 = get(a[i] - b[i]);
		ans += 1LL*ask(c2-1);
		add(c1);
	}
	cout << ans;
	
	return 0;
}

E - Sleeping Schedule
题目大意:一个人会醒来n次.每次醒来之后可以在a[i]或者a[i]-1之后睡回去.一天有h小时,睡一次也是h小时.如果在睡的时候在[l,r]区间,就是一次好的睡眠.问最大的好的睡眠次数.
用学长…就是一眼dp题.转移的很明显.不过因为本人是个dp苦手,还是修修改改了30分钟才交出来.dp[i][j]表示第i次在j时候睡觉最大的good睡眠次数.一开始初始化为-1,那转移的方式就是如果dp[i-1][j] != -1 那么就可以更新dp[i][j+a[i]]和dp[i][j+a[i]-1]两个位置.要记得取模,代码比我的话要好理解一点吧…

#pragma GCC optimize(3)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=b;++i)
#define afir(i,a,b) for(int i=a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#include <bits/stdc++.h>
 
using namespace std;
const int N = 2e3+10;
inline int read(){
	int x = 0,f=1;char ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void write(int k) {
    if (k < 0)
        putchar('-'), k = -k;
    if (k >= 10)
        write(k / 10);
    putchar(k % 10 + '0');
}
int n,h,l,r,a[N],dp[N][N];
int main(){
	cin >> n >> h >> l >> r;
	mem(dp,-1);
	dp[0][0] = 0;
	int ans = 0;
	fir(i,1,n){
		cin >> a[i];
		fir(j,0,h){
			if(dp[i-1][j] > -1){
				int c = (j+a[i])%h;
				if(c >= l && c <= r) dp[i][c] = max(dp[i][c],dp[i-1][j] + 1);
				else dp[i][c] = max(dp[i][c],dp[i-1][j]);
				ans = max(ans,dp[i][c]);
				c = (j+a[i]-1+h)%h;
				if(c >= l && c <= r) dp[i][c] = max(dp[i][c],dp[i-1][j] + 1);
				else dp[i][c] = max(dp[i][c],dp[i-1][j]);
				ans = max(ans,dp[i][c]);
			}
		}
	}
	cout << ans;
	
	return 0;
}

F. Maximum White Subtree(待更)

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/106121463