Educational Round 58 (Rated for Div. 2)

题目:https://codeforces.com/contest/1101

A题(过)
求是k的倍数且不在区间[l,r]里的最小数 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int q;
int main(){
	scanf("%d",&q);
	while(q--){
		ll l,r,k,t;
		cin>>l>>r>>k;
		if(k<l|| k>r){
			cout<<k<<endl;
		}else{
			t = (r-k)/k;
			cout<<k+(t+1)*k<<endl;
		}
	}
	return 0;
}
B题(过)
B题:求[:||||||:] 的最长长度
	关键是读题。。。一点要有[::]这四个,然后|||必须在::中间 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
char s[500005];
int a1,a2,a3,a4;
void solve(){
	int len = strlen(s+1);
	fo(i,1,len){
		if(s[i]=='['){
			a1 = i;
			break;
		}
	}
	if(a1==0){
		printf("-1\n");
		return;
	}
	fo(i,a1+1,len){
		if(s[i]==':'){
			a2 = i;
			break;
		}
	}
	if(a2==0){
		printf("-1\n");
		return;
	}
	for(int i=len; i>a2; i--){
		if(s[i]==']'){
			a4 = i;
			break;
		}
	}
	if(a4==0){
		printf("-1\n");
		return;
	}
	for(int i=a4-1; i>a2; i--){
		if(s[i]==':'){
			a3 = i;
			break;
		}
	}
	if(a3==0){
		printf("-1\n");
		return;
	}
	ll ans = 4;
	fo(i,a2+1,a3-1){
		if(s[i]=='|')ans++;
	}
	cout<<ans<<endl;
} 
int main(){
	scanf("%s",s+1);
	solve();
	return 0;
}
C题(过,忘记idx跟着排序Wa5)
题意,给n个区间,[l,r]要求把这n个区间分别放到两个集合里
如果区间有交集则必须放在同一个集合,要求两个集合都必须有区间(否则输出0)
输出每个区间所在集合 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
struct node{
	int l, r, idx;
	bool operator < (const node &p)const{
		return l<p.l;
	} 
}a[200005]; 
int t,n,ans[200005];
void solve(){
	sort(a+1,a+1+n);
	int lmx=0,rmx=0;
	bool flag = 1, t1=0, t2=0;
	fo(i,1,n){
		if(a[i].l<=lmx){
			lmx = max(lmx, a[i].r);
			ans[a[i].idx] = 1;
			t1=1;
			flag = 0;
		}else if(a[i].l<=rmx){
			rmx = max(rmx, a[i].r);
			ans[a[i].idx] = 2;
			t2=1;
			flag = 1;
		}else if(flag){
			t1=1;
			ans[a[i].idx] = 1;
			lmx = max(lmx, a[i].r);
			flag = 0;
		}else{
			t2=1;
			ans[a[i].idx] = 2;
			rmx = max(rmx, a[i].r);
			flag = 1;
		}
	}
	if(t1&&t2){
		fo(i,1,n){
			printf("%d ",ans[i]);
		}
		putchar(10);
	}else{
		cout<<"-1"<<endl;
	}
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		fo(i,1,n){
			scanf("%d%d",&a[i].l,&a[i].r);
			a[i].idx = i;
		}
		solve(); 
	}
	return 0;
}
E题(过)
题意:在线给出矩形[x,y],在线查询前面给出的矩形能否容纳在矩形[l,r]里(可重叠)输出YES or NO 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n;
ll l,r;
char c;
int main(){
	scanf("%d",&n);
	ll a1=0,a2=0,b1=0,b2=0; // a表示最长长的矩形的长宽,b表示最长宽的矩形的长宽 
	getchar();
	while(n--){
		scanf("%c%lld%lld",&c,&l,&r);
		getchar();
		if(l<r)swap(l,r);
		if(c=='+'){
			if(l>=a1){ // 找长最长的矩形 
				a1=l;
				a2=r;
			}
			if(r>=b1){ // 找宽最长的矩形 
				b1=r;
				b2=l;
			}
		}else{
			// 当无法包含的时候,肯定至少无法包含a,b两个之一 
			if(a1>l)puts("NO");
			else if(a1<=l&&a2>r)puts("NO");		
			else if(b2>l)puts("NO");
			else if(b2<=l&&b1>r)puts("NO");
			else puts("YES");
		}	
	}	
	return 0;	
}
D题(看题解)
看题解,读题也很麻烦
给出一棵树 
g(x,y)表示x到y的路径上的点包括(x,y),这整条路径上的数的公约数
要求路径上的点都必须有一个共同的约数
如果不存在一个g(x,y)>1输出0 
(因为路径可以是一个点,所以只要有一个数大于1就不是0了,坑!!!) 
求这条路径的最长深度 

题解:
	先预处理出所有质数
	然后以分别每个质数nowPri作为约数求出倍数u 
	以u为一个点进行深索最长的路径(整条路径都必须以nowPri作为约数),更新答案 
#include<bits/stdc++.h>
#define ll long long 
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 200005;
int n,a[maxn],vis[maxn],dp[maxn],ans;
vector<int> G[maxn],num[maxn],prime;
int cnt,nowPri; // 以nowPri为约数的标记为cnt 
void getPrime(){
	fo(i,2,maxn-1){	
		if(vis[i])continue;
		prime.push_back(i);
	//	cout<<i<<endl; 
		for(int j=i; j<maxn; j+=i) vis[j]=1;
	}
}
// 寻找约数为nowPri的最长路径 
void dfs(int u,int par){
	int mx1=0,mx2=0; // 最深子树,次深子树
	dp[u]=1;
	vis[u]=cnt;
	for(int v : G[u]){
		if(a[v]%nowPri!=0||v==par)continue; // 不是当前约数的倍数 
		dfs(v,u);
		dp[u] = max(dp[u], 1+dp[v]); // 更新本节点的最大深度 
		if(dp[v]>=mx1){
			mx2=mx1;mx1=dp[v];
		}else if(dp[v]>=mx2){
			mx2=dp[v];
		}
	} 
	ans = max(ans, 1+mx1+mx2);
}
void solve(){
	getPrime();
	memset(vis,0,sizeof(vis));
	for(int pri : prime){ // 枚举同一个约数 
		cnt++;
		nowPri = pri;
		for(int j=pri; j<maxn; j+=pri){ // 该约数的倍数 
			for(int u : num[j]){ // 数字为j的节点u,枚举一个端点 
				if(vis[u]!=cnt){ // 没有被访问过的顶点 
					dfs(u,u);	
				}
			}
		}
	}
	cout<<ans<<endl; 
}
int main(){
	scanf("%d",&n);
	fo(i,1,n){
		scanf("%d",&a[i]);
		num[a[i]].push_back(i);
	} 
	int u,v;
	fo(i,2,n){
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	solve();
	return 0;
} 
F题
G题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值