算法競賽訓練實錄


Codeforces Round 603

4題 rank1985

ABCD

都是很水的題。 cout << 000輸出0,而cout<<"000"才輸出000,因為這個WA6次要被笑(打)死。

E

判定括號序列合法性:每一個前綴和不小於0,同時最后一個前綴和等於0.線段樹更新即可.新技能Get.

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int minz[maxn*4],tg[maxn*4],maxz[maxn*4],tg2[maxn*4];
char s[maxn];
inline int ls(int x){
	return x<<1;
}
inline int rs(int x){
	return x<<1|1;
}
void pushdown(int rt){
	if(tg[rt]==0) return;
	minz[ls(rt)]+=tg[rt];
	tg[ls(rt)]+=tg[rt];
	minz[rs(rt)]+=tg[rt];
	tg[rs(rt)]+=tg[rt];
	tg[rt]=0;
}
void pushdown2(int rt){
	if(tg2[rt]==0) return;
	maxz[ls(rt)]+=tg2[rt];
	tg2[ls(rt)]+=tg2[rt];
	maxz[rs(rt)]+=tg2[rt];
	tg2[rs(rt)]+=tg2[rt];
	tg2[rt]=0;
}
int upd(int il,int ir,int d,int rt,int l,int r){
	if(il>r||ir<l) return minz[rt];
	if(l>=il&&r<=ir){
		minz[rt]+=d;
		tg[rt]+=d;
		return minz[rt];
	}
	pushdown(rt);
	int mid=(l+r)>>1;
	return minz[rt]=min(upd(il,ir,d,ls(rt),l,mid),upd(il,ir,d,rs(rt),mid+1,r));
}
int ask(int il,int ir,int rt,int l,int r){
	if(il>r||ir<l) return 0x3f3f3f3f;
	if(l>=il&&r<=ir) return minz[rt];
	pushdown(rt);
	int mid=(l+r)>>1;
	return min(ask(il,ir,ls(rt),l,mid),ask(il,ir,rs(rt),mid+1,r));
}
int upd2(int il,int ir,int d,int rt,int l,int r){
	if(il>r||ir<l) return maxz[rt];
	if(l>=il&&r<=ir){
		maxz[rt]+=d;
		tg2[rt]+=d;
		return maxz[rt];
	}
	pushdown2(rt);
	int mid=(l+r)>>1;
	return maxz[rt]=max(upd2(il,ir,d,ls(rt),l,mid),upd2(il,ir,d,rs(rt),mid+1,r));
}
int ask2(int il,int ir,int rt,int l,int r){
	if(il>r||ir<l) return 0;
	if(l>=il&&r<=ir) return maxz[rt];
	pushdown2(rt);
	int mid=(l+r)>>1;
	return max(ask2(il,ir,ls(rt),l,mid),ask2(il,ir,rs(rt),mid+1,r));
}
int st[maxn];
int main(){
	int n;
	scanf("%d",&n);
	scanf("%s",s+1);
	int cur=1;
	for(int i=1;i<=n;i++){
		if(s[i]=='L') cur=max(1,cur-1);
		else if(s[i]=='R') {
			cur++;
		}
		else if(s[i]=='(') {
			if(st[cur]==1) ;
			else if(st[cur]==0){
				st[cur]=1;
				upd(cur,n,1,1,1,n);
				upd2(cur,n,1,1,1,n);
			}
			else {
				st[cur]=1;
				upd(cur,n,2,1,1,n);
				upd2(cur,n,2,1,1,n);
			}
		}
		else if(s[i]==')'){
			if(st[cur]==-1);
			else if(st[cur]==0){
				st[cur]=-1;
				upd(cur,n,-1,1,1,n);
				upd2(cur,n,-1,1,1,n);
			}
			else {
				st[cur]=-1;
				upd(cur,n,-2,1,1,n);
				upd2(cur,n,-2,1,1,n);
			}
		}
		else{
			if(st[cur]==0) ;
			else if(st[cur]==1){
				st[cur]=0;
				upd(cur,n,-1,1,1,n);
				upd2(cur,n,-1,1,1,n);
			}
			else {
				st[cur]=0;
				upd(cur,n,1,1,1,n);
				upd2(cur,n,1,1,1,n);
			}
		}
		if(ask(1,n,1,1,n)>=0&&ask(n,n,1,1,n)==0){
			printf("%d ", ask2(1,n,1,1,n));
		}
		else printf("-1 ");
	}
	return 0;
}

Codeforces Round 604

4題 rank 252

B

單調棧正反掃一遍,找每個數左邊和右邊第一個比它大的數的位置,位置之差等於它本身則成立,否則不成立。

似乎有更簡單的做法。。懶得看了

#include <bits/stdc++.h>
using namespace std;
char ans[200005];
int a[200005];
int stk[200005],id[200005];
int l[200005],r[200005],pos[200005];
int main(){
	int T;
	cin >> T;
	while(T--){
		int n;
		cin >> n;
		for(int i=1;i<=n;i++) cin >> a[i],pos[a[i]]=i;
		int hd=0;
		int i=1;
		stk[0]=0x3f3f3f3f;  id[0]=0;
		while(i<=n){
			while(stk[hd]<a[i]) hd--;
			l[i]=id[hd]+1;
			stk[++hd]=a[i];
			id[hd]=i;
			i++;
		}
		i=n; hd=0; id[0]=n+1;
		while(i>0){
			while(stk[hd]<a[i]) hd--;
			r[i]=id[hd]-1;
			stk[++hd]=a[i];
			id[hd]=i;
			i--;
		}
		for(i=1;i<=n;i++){
			int j=pos[i];
			if(r[j]-l[j]+1==i) ans[i]='1';
			else ans[i]='0';
		//	cout << l[i] << " " << r[i] << endl;
		}
		for(i=1;i<=n;i++) cout << ans[i];
		cout << endl;
	}
	return 0;
}

E

簡單遞推題,居然花了大段時間求無窮級數(居然還沒求出來)。。。

\(f(x)\)為到第\(x\)天的期望,那么顯然有\(f(x)=p(i-1)*(f(x-1)+1)+(1-p(i-1))*(f(x)+f(x-1)+1)\)

解得 \(f(x)=(f(x-1)+1)/p(i-1)\) 求出\(f(n+1)\)即可

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
int qpow(int x,int y){
	int res=1,bas=x;
	while(y){
		if(y&1) res=1ll*res*bas%mod;
		bas=1ll*bas*bas%mod;
		y>>=1;
	}
	return res%mod;
}
int p[200005];
int dp[200005];
int main(){
	int n;
	cin >> n;
	for(int i=1;i<=n;i++) cin >> p[i];
	dp[1]=0;
	for(int i=2;i<=n+1;i++){
		dp[i]=(1ll*(dp[i-1]+1)*qpow(p[i-1],mod-2)%mod)*100%mod;
	}
	cout << dp[n+1];
	return 0;
} 

codeforces EDU round 78

3題rk891

A

memcmp函數返回值:相等為0,小於時小於0,大於時大於0

B

猜想:對於\(1\)\(n\)的和\(\frac{n*(n+1)}{2}\),對於任意\(0\leq s \leq \frac{n*(n+1)}{2}\),總能找到\(1\)\(n\)的子集,使其元素和為\(s\).

證明:\(s\)有兩種情況:1)小於等於\(n\),問題解決;2)大於\(n\),則將\(s\)減去\(n\),此時\(s\)小於等於\(1\)到n-1的和,問題轉化為1到n-1的情況;如此遞歸下去,得證。

C

枚舉左邊,判斷右邊,map維護

D

左端點排序,掃描線從左到右即可。

不會T的理由是並查集至多合並\(n\)次就一定可以break出來

#include <bits/stdc++.h>
using namespace std;
struct node{
	int l,r;
}p[500005];
int id[1000005];
set<int> sr;
int fa[500005];
int find(int x){
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
bool cmp(node x,node y){
	return x.l<y.l;
}
bool join(int u,int v){
	int x=find(u),y=find(v);
	if(x==y) return false;
	fa[x]=y;
	return true;
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&p[i].l,&p[i].r);
		fa[i]=i;
	}
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n;i++) id[p[i].l]=id[p[i].r]=i;
	sr.insert(p[1].r);
	bool ff=true;
	for(int i=2;i<=n;i++){
		set<int>::iterator it = sr.begin();
		vector<int> tmp;
		for(;it!=sr.end();it++){
			if(p[i].l>*it) {
				tmp.push_back(*it);
			}
			else break;
		}
		for(int j=0;j<int(tmp.size());j++) sr.erase(tmp[j]);
		it=sr.begin();
		bool f=true;
		for(;it!=sr.end();it++){
			if(p[i].r>*it){
				f=join(i,id[*it]);
			}
			else break;
			if(!f){
				break;
			}
		}
		if(!f){
			ff=false;
			break;
		}
		sr.insert(p[i].r);
	}
	int cnt=0;
	for(int i=1;i<=n;i++) if(find(i)==i) cnt++;
	if(cnt>1) ff=false;
	if(ff) cout << "YES\n";
	else cout << "NO\n";
	return 0;
} 

codeforces edu round 80

C

\(dp1[i][j]\)表示a數組第i位為j有多少種,\(dp2[i][j]\)表示b數組。。。這么簡單怎么就想不出來

D

顯然是二分答案。judge應該狀態壓縮,將每一行壓縮為一個數,數位為1表示這一位大於等於x,否則為0,那么只要存在兩行i,j其\(num(i)|num(j)==2^{m}-1\)即可。而狀態數至多\(2^m\)個。

E

這一題極其重要。

首先應該快速反應過來最小值不是i就是1

考慮最大值:考慮任何一個朋友x,假設他在一段區間內都沒有被移到隊首,考察其他朋友對他的影響:假設朋友i在他右邊並被移到隊首,那么x的位置加一,而在這之后朋友i的移動都不會對x產生任何影響,因而可以知道x在這段區間內向右移動次數為這段區間內不同朋友的個數。這可以用主席樹完成。而x沒有被操作的區間顯然就是它相鄰兩次被操作的區間。不過從一開始到x被操作的區間需要求比他大的不同朋友個數,這可以用BIT實時更新來求出來。所有區間取max即可。

主席樹任何一次單點更新都將產生一棵新樹,不可直接在原樹上修改!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM