【Codeforces Round #569 (Div. 2)】 題解

A

小學數學題

#include<bits/stdc++.h>

using namespace std;
long long f[102];
void init(){
	f[1]=1;
	for(int i=2;i<=101;i++){
		f[i]=f[i-1]+(i-1)*4;
	}
}
int main(){
	init();
	int n;
	cin>>n;cout<<f[n]<<endl;
	return 0;
}

B

題意:

現在有一個數組,你可以選擇若干個aia_i將它們變成ai1-a_i-1,使得他們的乘積最大。輸出一種可行方案

思路:

先把所有的非負數變爲ai1-a_i-1,然後統計現在負數的個數,若爲偶數,則不操作,否則選擇最小的那個負數變爲ai1-a_i-1

代碼:

#include<bits/stdc++.h>

using namespace std;
const int N = 1e6+100;
int a[N];
int main(){
	int n;
	int neg=0;
	cin>>n;for(int i=1;i<=n;i++){
		cin>>a[i];if(a[i]>=0) a[i]=-a[i]-1;
	} 
	for(int i=1;i<=n;i++){
		if(a[i]<0) neg++;
	}
	if(neg&1){
		int minn=0;
		for(int i=1;i<=n;i++) minn=min(minn,a[i]);
		for(int i=1;i<=n;i++){
			if(a[i]==minn){
				a[i]=-a[i]-1;break;
			}
		}
	}
	for(int i=1;i<=n;i++) cout<<a[i]<<' ';
	cout<<endl;
	return 0; 
}

C

題意:

一個長度爲nn的雙端隊列,你執行無數次下列操作:取出隊列頂端的前兩個數a,ba,b,大的放在隊列頂端,小的放到隊列尾部,現在給你qq次查詢,查詢每次操作的a,ba,b

思路:

手動模擬一遍一會發現,前nn次是不確定的,經過nn次之後變成了每n1n-1次一個循環,因此只需先記錄2n12*n-1次,然後對於查詢直接查詢即可,複雜度O(nlog(n))O(n*log(n))

代碼:

#include<bits/stdc++.h>

using namespace std;
int main(){
	long long n,m,x;
	scanf("%I64d%I64d",&n,&m); 
	map<long long ,pair<long long,long long> > mmp1,mmp2;
	deque<long long> q;
	for(int i=1;i<=n;i++){
		scanf("%I64d",&x);q.push_back(x);
	}
	for(int j=1;j<=n;j++){
		int A=q.front();q.pop_front();
		int B=q.front();q.pop_front();
		//cout<<j<<' '<<A<<' '<<B<<endl;
		mmp1[j]={A,B};
		if(A>B){
			q.push_front(A);
			q.push_back(B);
		}
		else{
			q.push_front(B);
			q.push_back(A);			
		}
	}
	for(int j=1;j<=n-1;j++){
		int A=q.front();q.pop_front();
		int B=q.front();q.pop_front();
		//cout<<j<<' '<<A<<' '<<B<<endl;
		mmp2[j]={A,B};
		if(A>B){
			q.push_front(A);
			q.push_back(B);
		}
		else{
			q.push_front(B);
			q.push_back(A);			
		}
	}
	long long Q;
	while(m--){
		scanf("%I64d",&Q);
		if(Q<=n){
			printf("%I64d %I64d\n",mmp1[Q].first,mmp1[Q].second);
		}
		else{
			Q-=n;
			if(Q%(n-1)==0) printf("%I64d %I64d\n",mmp2[n-1].first,mmp2[n-1].second);
			else printf("%I64d %I64d\n",mmp2[Q%(n-1)].first,mmp2[Q%(n-1)].second);
		}
	}
	return 0;
} 

D

題意:

一個nmn*m的網狀圖,你要訪問每個格點,你的初始格點在(1,1)(1,1),現在你可以從(x,y)(x,y)到達(x+dx,y+dy)(x+dx,y+dy),你要構造一個遍歷順序使得每次的dx,dydx,dy都不相同並且能遍歷完所有的點。

思路

(1,1)&gt;(n,m)&gt;(n,m1)&gt;(1,2)&gt;......&gt;(n,1)&gt;(2,1).....(1,1)-&gt;(n,m)-&gt;(n,m-1)-&gt;(1,2)-&gt;......-&gt;(n,1)-&gt;(2,1).....

#include<bits/stdc++.h>

using namespace std;
int main(){
	int n,m;cin>>n>>m;
	for(int i=1;i<=n/2;i++){
		for(int j=1;j<=m;j++){
			printf("%d %d\n",i,j);
			printf("%d %d\n",n+1-i,m+1-j);
			//<<n+1-i<<' '<<m+1-j<<endl;
		} 
	}
	if(n&1){
		if(m&1){
			for(int i=1;i<=m/2;i++){
				printf("%d %d\n",n/2+1,i);
				printf("%d %d\n",n/2+1,m+1-i);
			}
			printf("%d %d\n",n/2+1,m/2+1);
			//cout<<n/2+1<<' '<<m/2+1<<endl; 
		}
		else{
			for(int i=1;i<=m/2;i++){
				printf("%d %d\n",n/2+1,i);
				printf("%d %d\n",n/2+1,m+1-i);
				//cout<<n/2+1<<' '<<m+1-i<<endl;
			}			
		}
	}
	return 0;
}

E

題意:

nn盤菜,mm個學生,每盤菜的價格爲aia_i,每個學生帶的錢爲bib_i,每個學生會買他所能買的最貴的菜,現在有qq次修改,每次你可以把aia_i變爲xx,或者把bib_i變爲xx,對於每次修改,計算剩下的最貴的菜的價格,如果沒有,則輸出1-1

思路:

對於每個aia_i,我們將區間[1,ai][1,a_i]11,對於每個bib_i,我們將區間[1,bi][1,b_i]11,每次查詢統計最大的不爲00的數,如果沒有輸出1-1,線段樹即可完成操作,複雜度O(nlog(n))O(n*log(n))

代碼:

#include<bits/stdc++.h>

using namespace std;
const int N = 2e6+100;
int tag[N<<1],maxx[N<<1];
int a[N],b[N];
void pushdown(int rt,int l,int r){
	if(tag[rt]){
		tag[rt<<1]+=tag[rt];
		tag[rt<<1|1]+=tag[rt];
		maxx[rt<<1]+=tag[rt];
		maxx[rt<<1|1]+=tag[rt];
		tag[rt]=0;
	}
}
void update(int rt,int nl,int nr,int l,int r,int x){
	if(nl<=l&&r<=nr){
		maxx[rt]+=x;
		tag[rt]+=x;
		return ;
	}
	int mid=(l+r)>>1;
	pushdown(rt,l,r);
	if(nl<=mid) update(rt<<1,nl,nr,l,mid,x);
	if(nr>mid) update(rt<<1|1,nl,nr,mid+1,r,x);
	maxx[rt]=max(maxx[rt<<1|1],maxx[rt<<1]);
}
int query(int rt,int l,int r){
	if(l==r){
		return l;
	}
	int mid=(l+r)>>1;
	pushdown(rt,l,r);
	if(maxx[rt<<1|1]>0){
		return query(rt<<1|1,mid+1,r);
	}
	return query(rt<<1,l,mid);
}
int main(){
	int n,m,q;
	scanf("%d %d",&n,&m);
	memset(maxx,0,sizeof(maxx));
	memset(tag,0,sizeof(tag));
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),update(1,1,a[i],1,2000002,1);
	for(int i=1;i<=m;i++) scanf("%d",&b[i]),update(1,1,b[i],1,2000002,-1);
	//cout<<query(1,1,2000002)<<endl;
	scanf("%d",&q);
	while(q--){
		int op,id,num;
		scanf("%d %d %d",&op,&id,&num);
		if(op==1){
			update(1,1,a[id],1,2000002,-1);
			a[id]=num;
			update(1,1,a[id],1,2000002,1);
		}
		else{
				update(1,1,b[id],1,2000002,1);
				b[id]=num;
				update(1,1,b[id],1,2000002,-1);		
		}
		int ok=query(1,1,2000002);
		if(maxx[1]<=0) puts("-1");
		else printf("%d\n",ok);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章