CF1872

Link
A Two Vessels
十分甚至九分地简单

#include<bits/stdc++.h>
using namespace std;
int t;
int a,b,c;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&a,&b,&c);
		c<<=1;
		a=abs(a-b);
		printf("%d\n",a/c+((a%c)==0?0:1));
	}
	return 0;
}

B he Corridor or There and Back Again
我们只需要让这个小人一直往右走,然后不断更新能到达地最右边地距离就行了。
注意陷阱启动时踏入房间也不行就可以了.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime>
#include<bitset>
using namespace std;
int t;
struct trap{
	int d;
	int s;
}tr[500];
int n;
int k;
int maxx;
int pl[500];
int main(){
	scanf("%d",&t);
	while(t--){
		memset(pl,0x3f,sizeof(pl));
		scanf("%d",&n);
		for(int i=1;i<=n;++i){
			scanf("%d%d",&tr[i].d,&tr[i].s);
			pl[tr[i].d]=min(tr[i].s,pl[tr[i].d]);
		}
		maxx=8000000;
		for(int i=1;i<=400;++i){
			if(i>maxx) {
				k=i-1;
				break;		
			}else{
				maxx=min(maxx,i+(pl[i]-1)/2);
			}
		}
		printf("%d\n",k);
	}
	return 0;
}

C. Non-coprime Split
很显然如果存在偶数在范围内的话,一般时可以的。
如果没有,那么这个奇数时质数地话就不可以
然后特判几个特殊情况即可。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime>
#include<bitset>
using namespace std;
int t;
int l,r;
int f;
int pri;
void dis(int l){
	for(int i=2;i*i<=l;++i){
		if(l%i==0){
			if(!f){
				f=1;
				pri=i;
				return ;
			}
		}
	}
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&l,&r);
		if(l!=r){
			if((l==2&&r==3)||(l==1&&r==2)||(l==1&&r==3)){
				printf("-1\n");
				continue;
			}else{
				if(r%2!=0) r--;
				printf("%d %d\n",r/2,r/2);
			}
		}else{
			if(l==1||l==2||l==3){
				printf("-1\n");
				continue;
			}
			f=0;
			dis(l);
			if(!f){
				printf("-1\n");
				continue;
			}else{
				printf("%d %d\n",pri,l-pri);
			}
		}
	}
	return 0;
}

D. Plus Minus Permutation
显然只要区分开只在前面,只在后面和前后都有的就可以了.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime>
#include<bitset>
using namespace std;
int t;
long long ans;
long long n,x,y;
long long gcd(long long x,long long y){
	return y==0?x:gcd(y,x%y);
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%lld%lld%lld",&n,&x,&y);
		long long gc=gcd(x,y);
		gc=x/gc*y;
		gc=n/gc;
		x=n/x-gc;
		y=n/y-gc;
		ans=((n+n-x+1)*x/2)-(1+y)*y/2;
		cout<<ans<<endl;
	}
	return 0;
}

E. Data Structures Fan
考虑一下异或的独特性质,异或两次为0
所以一开始算出只有1和只有0的值,然后如果要改变\([l,r]\),那么就把这两个范围内的数的异或和去异或上就行了。
对于两种答案的影响是一样的.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime>
#include<bitset>
using namespace std;
int t;
int n;
int a[100005];
string s;
int ans[2];
int q;
int x,y;
int f;
int sum[100005][2];
int su[100005];
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		memset(sum,0,sizeof(sum));
		ans[0]=ans[1]=0;
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
		}
		cin>>s;
		for(int i=1;i<=n;++i){
			if(s[i-1]=='0'){
				sum[i][0]=sum[i-1][0]^a[i];
				sum[i][1]=sum[i-1][1];
			}else{
				sum[i][1]=sum[i-1][1]^a[i];
				sum[i][0]=sum[i-1][0];
			}
			su[i]=su[i-1]^a[i];
		}
		ans[1]=sum[n][1];ans[0]=sum[n][0];
		scanf("%d",&q);
		while(q--){
			scanf("%d",&f);
			if(f==1){
				scanf("%d%d",&x,&y);
				ans[0]^=(su[y]^su[x-1]);
				ans[1]^=(su[y]^su[x-1]);
			}else{
				scanf("%d",&x);
				printf("%d ",ans[x]);
			}
		}
		cout<<endl;
	}
	return 0;
}

F. Selling a Menagerie
这个非常简单的图论和贪心问题.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime>
#include<bitset>
#define int long long
using namespace std;
int t;
int n;
int a[100005];
int c[100005];
int du[1000001];
queue<int> q,ans;
int tem[100005];
int k;
int h;
int minn;
void dfs(int f,int now){
	if(minn>c[now]){
		k=now;
		minn=c[now];
	}
	tem[++h]=now;
	du[a[now]]--;
	if(!(a[now]==f)){
		dfs(f,a[now]);
	}
}
signed main(){
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		for(int i=1;i<=n;++i){
			scanf("%lld",&a[i]);
			du[a[i]]++;
		}
		for(int i=1;i<=n;++i){
			scanf("%lld",&c[i]);
		}
		for(int i=1;i<=n;++i){
			if(du[i]==0){
				q.push(i);
				ans.push(i);
			}
		}
		while(!q.empty()){
			int x=q.front();
			q.pop();
			du[a[x]]--;
			if(du[a[x]]==0){
				q.push(a[x]);
				ans.push(a[x]);
			}
		}
		for(int i=1;i<=n;++i){
			if(du[i]!=0){
				minn=1000000009;
				h=0;
				dfs(i,i);
				for(int i=1;i<=h;++i){
					if(tem[i]==k){
						for(int j=i+1;j<=h;++j){
							ans.push(tem[j]);
						}
						for(int j=1;j<i;++j){
							ans.push(tem[j]);
						}
						ans.push(k);
						break;
					}
				}		
			}
		}
		while(!ans.empty()){
			printf("%lld ",ans.front());
			ans.pop();
		}
		cout<<endl;
	}
	return 0;
}

G. Replace With Product
对于这个题目,首先我们可以想到,对于两边的1,显然是不应该包括进去的。
那么我们假设我们已经选定了\([l,r]\) ,现在这一部分的的贡献是\(p\),然后把\(a_l\)删掉的话,
答案会变化\(-p+\frac{p}{a_i}+a_i\),再考虑一下极端情况,剩下的有全是\(1\),并且原来有\(n\)个数,那么答案就会变成只要\(p>n\)就会更优。
而该情况不满足下,很容易注意到并不会有很多不是1的数存在,就可以枚举了。
当然,可以选择更大的上限,效果是一样的,例如\(4\times10^5\)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime>
#include<bitset>
#define int long long
using namespace std;
int t;
int n;
const int maxn=200005;
int sum[200005];
int num[maxn];
int a[200005];
int tem;
int h;
long long ans,al,ar;
signed main(){
	scanf("%lld",&t);
	while(t--){
		scanf("%lld",&n);
		for(int i=1;i<=n;++i){
			scanf("%lld",&a[i]);
		}
		long long l=1;
		h=0;
		long long r=n;
		while(l<=n&&a[l]==1) l++;
		while(r>=1&&a[r]==1) r--;
		if(l>=r){
			if(l>n) l--;
			printf("%lld %lld\n",l,l);
			continue;
		}
		int f=0;
		long long tem=1;
		for(int i=l;i<=r;++i){
			tem*=a[i];
			if(tem>(r-l+1)*2){
				f=1;
				break;
			}
		}
		if(f){
			printf("%lld %lld\n",l,r);
		}else{
			for(int i=l;i<=r;++i){
				if(a[i]!=1){
					num[++h]=i;
				}
			}
			for(int i=1;i<=n;++i){
				sum[i]=sum[i-1]+a[i];
			}
			long long tem=1;
			ans=0;
			al=l;
			ar=r;
			for(int i=1;i<=h;++i){
				tem=1;
				for(int j=i;j<=h;++j){
					tem*=a[num[j]];
					if((sum[n]-sum[num[j]]+sum[num[i]-1]+tem)>ans){
						ans=sum[n]-sum[num[j]]+sum[num[i]-1]+tem;
						al=num[i];
						ar=num[j];
					}
				}
			}
			printf("%lld %lld\n",al,ar);
		}
	}
	return 0;
}
posted @ 2023-09-09 11:00  Simex  阅读(3)  评论(0编辑  收藏  举报