【恢复计划】CF ROUND 620 div2 简要题解

【恢复计划】CF ROUND 620 div2 简要题解

找神腮要了一个简单场

A - Two Rabbits

判断\((a+b)|(x-y)\)​就行了

//@winlere
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>

using namespace std;
typedef long long ll;
int qr(){
	int ret=0,c=getchar();
	while(!isdigit(c)) c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return ret;
}

ll gcd(ll a,ll b){
	if(!b) return a;
	return gcd(b,a%b);
}

int main(){
	int T=qr();
	while(T--){
		ll x=qr(),y=qr(),a=qr(),b=qr();
		ll z=y-x,d=gcd(z,a+b);
		if(d==a+b) cout<<z/(a+b)<<endl;
		else cout<<"-1"<<endl;
	}
	return 0;
}

B - Longest Palindrome

因为保证的所有字符串长度都是m,因此贪心的能放就放就行(对于一个串,找是否存在它的reverse之后的串,如果有就直接放)。

但是有一个特殊情况,就是自我对称的串,这个直接放在中间就行

//@winlere
#include<iostream>
#include<set>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;
const int maxn=105;
string data[maxn],ans,self;
multiset<string> s;

int main(){
	int n,m;
	cin>>n>>m;
	for(int t=1;t<=n;++t) {
		cin>>data[t];
		string f=data[t];
		reverse(f.begin(),f.end());
		auto it=s.find(f);
		if(it!=s.end()) ans=data[t]+ans+f,s.erase(it);
		else s.insert(data[t]);
	}
	for(auto t:s){
		auto f=t;
		reverse(f.begin(),f.end());
		if(f==t){
			int siz=ans.size();
			if(siz==0) ans=t;
			else ans.insert(siz/2,f);
			break;
		}
	}
	cout<<ans.size()<<endl<<ans<<endl;	
	return 0;
}


C - Air Conditioner

容易证明,任何一个时间点,可以达到的温度是一个连续的区间,因此维护这个可行区间就行。时间会延伸这个可行区间,顾客的要求会限制这个可行区间,复杂度\(O(n)\)

//@winlere
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;

int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c=='-',c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;			   
}
const int maxn=505;
struct Peroid{
	int l,r;
	Peroid(int a=-1e9,int b=1e9):l(a),r(b){}
	Peroid operator + (Peroid f){
		int L=max(l,f.l),R=min(r,f.r);
		if(L>R) return Peroid(1e9,-1e9);
		return Peroid(L,R);
	}
	Peroid operator + (int d){
		return Peroid(l-d,r+d)+Peroid();
	}
};

int main(){
	int T=qr();
	while(T--){
		int n=qr(),m=qr(),tim=0;
		Peroid now(m,m);
		for(int t=1;t<=n;++t){
			int cur=qr(),l=qr(),r=qr();
			Peroid cur1(l,r);
			now=now+(cur-tim)+cur1;
			tim=cur;
		}
		if(now.l<=now.r) puts("YES");
		else puts("NO");
	}
	return 0;
}


D - Shortest and Longest LIS

虽然退役多年,但还是记得一些套路。

构造一个最长的LIS,理论上界是所有连续的\(<\)号连接的数字都是LIS的一部分,这是上界,下面我将构造出这个上界:

初始有一个\(1\ 2\ 3 \dots\),然后将所有\(>\)的连续段reverse就行了。

同样的方法,构造一个最小的LIS,理论下界是最长的连续\(>\)​号,这是下界,下面我将构造出这个下界

初始有一个\(n \ n-1 \ \dots 3 \ 2 \ 1\)

然后把所有的\(<\)的连续段reverse就行了。

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

const int maxn=2e5+5;
int qr(){
	int ret=0,c=getchar();
	while(!isdigit(c)&&c!='<'&&c!='>') c=getchar();
	if(c=='<')  return 0;
	if(c=='>')  return 1;
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return ret;
}
int data[maxn],ans[maxn];

int main(){
	int T=qr();
	while(T--){
		int n=qr();
		for(int t=1;t<n;++t) data[t]=qr();
		for(int t=1;t<=n;++t) ans[t]=n-t+1;
		for(int t=1,r=1;t<n;t=++r){
			while(r<n&&data[r]==0) ++r;
			reverse(ans+t,ans+r+1);
		}
		for(int t=1;t<=n;++t) printf("%d ",ans[t]);
		putchar('\n');
		for(int t=1;t<=n;++t) ans[t]=t;
		for(int t=1,r=1;t<=n;t=++r) {
			while(r<n&&data[r]==1) ++r;
			reverse(ans+t,ans+r+1);
		}
		for(int t=1;t<=n;++t) printf("%d ",ans[t]);
		putchar('\n');
	}
	return 0;
}

E - 1-Trees and Queries

由于可以重复走一个边,因此可行性之和两点之间的最短路的奇偶性有关了

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
int qr(){
	int ret=0,c=getchar(),f=0;
	while(!isdigit(c)) f=c=='-',c=getchar();
	while( isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}
const int maxn=1e5+5;
vector<int> e[maxn];
void add(int a,int b){e[a].push_back(b);e[b].push_back(a);}
int lg[maxn],r[21][maxn],dep[maxn],n,m;
void dfs(int now,int last){
	r[0][now]=last; dep[now]=dep[last]+1;
	for(int t=1;t<=lg[dep[now]];++t)
		r[t][now]=r[t-1][r[t-1][now]];
	for(auto t:e[now])
		if(t^last)
			dfs(t,now);
}

int LCA(int u,int v){
	if(dep[u]<dep[v]) swap(u,v);
	for(int t=lg[dep[u]];~t;--t)
		if(dep[r[t][u]]>=dep[v])
			u=r[t][u];
	if(u==v) return u;
	for(int t=lg[dep[u]];~t;--t)
		if(r[t][u]!=r[t][v])
			u=r[t][u],v=r[t][v];
	return r[0][u];
}

int getLen(int a,int b){
	int L=LCA(a,b);
	return dep[a]+dep[b]-dep[L]-dep[L];
}

int getAns(int a,int b,int x,int y,int k){
	int L1=getLen(a,b),L2=getLen(a,x)+getLen(y,b)+1;
	if( (!((L1^k)&1))&&L1<=k ) return 1;
	if( (!((L2^k)&1))&&L2<=k ) return 1;
	return 0;
}

int main(){
	for(int t=2;t<maxn;++t) lg[t]=lg[t>>1]+1;
	n=qr();
	for(int t=1;t<n;++t) add(qr(),qr());
	dfs(1,0);
	m=qr();
	for(int t=1;t<=m;++t){
		int x=qr(),y=qr(),a=qr(),b=qr(),k=qr();
		puts(getAns(a,b,x,y,k)||getAns(a,b,y,x,k)?"YES":"NO");
	}
	return 0;
}


posted @ 2021-08-07 17:34  谁是鸽王  阅读(50)  评论(0编辑  收藏  举报