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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章