Codeforces Round #594 (Div. 2) 題解

題目鏈接:https://codeforces.com/contest/1248

 

A - Integer Points

水題

#include<bits/stdc++.h>
using namespace std;
const int mx = 1e5+5;
typedef long long ll;
int a[mx],b[mx]; 
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d",&n);
		ll c[2] = {0,0};
		ll d[2] = {0,0};
		for (int i=1;i<=n;i++) {
			scanf("%d",a+i);
			c[a[i]%2]++;
		}
		scanf("%d",&m);
		for (int i=1;i<=m;i++) {
			scanf("%d",b+i);
			d[b[i]%2]++;
		}
		printf("%lld\n",c[0]*d[0]+c[1]*d[1]);
	}
	return 0;
}

B - Grow The Tree

意思就是一半的和做一邊,另一半的和做另一邊,平方的話讓一邊越大越好就行了


#include<bits/stdc++.h>
using namespace std;
const int mx = 1e5+5;
typedef long long ll;
int a[mx],b[mx]; 
int main(){
	int n;
	scanf("%d",&n);
	int sum = 0;
	for(int i=1;i<=n;i++){
		scanf("%d",a+i);
		sum += a[i];
	}
	sort(a+1,a+1+n);
	int beg = n / 2,ret = 0;
	for (int i=1;i<=beg;i++)
		ret += a[i];
	printf("%lld\n",1ll*ret*ret+1ll*(sum-ret)*(sum-ret));
	return 0;
}

C - Ivan the Fool and the Probability Theory

不難證明除了黑白交替的方塊意外,其他的方塊數都是取決於第一行的擺放方案,後面跟隨第一行都擺放都是固定的。然後一行的dp方案只要記最後是連續兩個一樣的還是不一樣的方案數就可以,另外行數對黑白交替的方案數的影響其實是一樣的。

#include<bits/stdc++.h>
using namespace std;
const int mx = 1e5+5;
const int mod = 1e9 + 7; 
typedef long long ll;
ll dp[mx][2];
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	if (m > n) swap(n,m);
	dp[1][0] = 1;
	for (int i=2;i<=n;i++) {
		dp[i][0] = (dp[i-1][0]+dp[i-1][1])%mod;
		dp[i][1] = dp[i-1][0];
	}
	ll ans = (dp[n][0] + dp[n][1] - 1)*2 + (dp[m][0] + dp[m][1])*2;
	ans %= mod;
	printf("%lld\n",ans);
	return 0;
}

D2 - The World Is Just a Programming Task (Hard Version)

利用棧的原理如果括號最後不完全匹配,那麼肯定是會是這樣情況))))((((,那麼要想有解必須左括號數量等於右括號數量。

不難發現我們能操作的空間只有...)..)...(...(...也就是最多兩個不匹配的括號

1、將原來匹配的括號互換(()) ==> )()(

2、將兩個不匹配的變成0個,))(( ==> ()()

3、減少一個不匹配,)( ==>()

4、變換一個不匹配的位置 ())(== > )()(

#include<bits/stdc++.h>
using namespace std;
const int mx = 3e5+5;
const int mod = 1e9 + 7; 
typedef long long ll;
int n;
int sum[mx];
char s[mx];
int lp[mx],rp[mx],psiz;
int cnt[mx],lc[mx],rc[mx];
bool vis[mx],mark[mx];
int fa[mx];
bool get_pos() {
	stack <int> s1;
	int j = 0;
	for (int i=1;i<=n;i++) {
		if (s[i] == '(') {
			s1.push(i);
		} else {
			if (s1.empty()) {
				lp[psiz++] = i;
				mark[i] = 1;
				continue;
			}
			int now = s1.top();
			lc[now] = i, rc[i] = now;
			s1.pop();
		} 
	}
	if (s1.size() != psiz) return 0;
	reverse(lp,lp+psiz);
	while (!s1.empty()) {
		rp[j++] = s1.top();
		mark[rp[j-1]] = 1;
		s1.pop();
	}
	reverse(rp,rp+psiz);
	return 1;
}
inline int get_int(int l,int r) {
	return sum[r] - sum[l];
}
void get_val() {
	stack <int> s1;
	for (int i=1;i<=n;i++) {
		if (mark[i]) continue;
		if (s[i]=='(') {
			s1.push(i);
		} else {
			int now = s1.top();
			s1.pop();
			if (!s1.empty()) {
				cnt[s1.top()]++;
				fa[now] = s1.top();
			}
			else {
				sum[now]++;
				vis[now] = 1;
			}
		}
	}
}
int main(){
	scanf("%d",&n);
	scanf("%s",s+1);
	int ans,l,r;
	if(!get_pos()) return 0*puts("0\n1 1");
	get_val();
	for (int i=1;i<=n;i++) sum[i] += sum[i-1];
	rp[psiz] = n + 1;
	lp[psiz] = 0;
	sum[n+1] = sum[n];
	ans = get_int(lp[0],rp[0]) + (psiz > 0);
	l = 1,r = 1;
	for (int i=lp[0]+1;i<rp[0];i++) {
		if (s[i]=='(') {
			if (vis[i]){
				if (cnt[i] + 1 > ans) {
					ans = cnt[i] + 1;
					l = i, r = lc[i];
				}
			} else if (vis[fa[i]]){
				int ret = get_int(lp[0],rp[0]) + cnt[i] + 1 + (psiz > 0);
				if (ret > ans) {
					ans = ret;
					l = i, r = lc[i];
				}
			} 
		} 
	}
	if (psiz) {
		int ret = get_int(lp[1],rp[1]) - get_int(lp[0],rp[0])  + (psiz>1) + 1;
		if (ret > ans) {
			ans = ret;
			l = lp[0], r = rp[0];
		}
		if (psiz > 1) {
			ret = get_int(lp[2],rp[2]) + 2;
			ret -= get_int(lp[1],lp[0]) + get_int(rp[0],rp[1]);
			ret += (psiz > 2);
			if (ret > ans) {
				ans = ret;
				l = lp[1],r = rp[1];
			}
		}
		int L = lp[0];
		while (L != lp[1]) {
			if (vis[L]) {
				ret = get_int(lp[0],rp[0]) + 2;
				ret += cnt[L];
				if (ret > ans) {
					ans = ret;
					l = L, r = lc[L];
				}
			}
			L--;
		}
		int R = rp[0];
		while (R != rp[1]) {
			if (vis[R]) {
				ret = get_int(lp[0],rp[0]) + 2;
				ret += cnt[R];
				if (ret > ans) {
					ans = ret;
					l = R, r = lc[R];
				}
			}
			R++;
		}
	}
	printf("%d\n%d %d\n",ans,l,r);
	return 0;
}

E - Queue in the Train

用三個隊列維護:

1、優先隊列維護可以去泡麪的時間

2、在機子前排隊的隊列

3、可以取泡麪但是由於前面的人不在而還沒去的優先隊列

#include<bits/stdc++.h>
#define x first
#define y second 
using namespace std;
const int mx = 1e5+5;
const int mod = 1e9 + 7; 
typedef long long ll;
typedef pair <int,int> pa;
int n,m;
pa s[mx];
ll ret[mx];
int sum[mx];
priority_queue <int,vector<int>,greater<int>> sq;
queue <int> nq;
void add(int x,int v) {
	for (;x<=n;x+=x&(-x))
		sum[x] += v;
} 
int get_sum(int x) {
	int ans = 0;
	while (x) {
		ans += sum[x];
		x -= x&(-x);
	}
	return ans;
}
void to_queue (int& j,ll times) {
	while (j <= n && s[j].x <= times) {
		if (get_sum(s[j].y) == s[j].y) {
			nq.push(s[j].y);
			add(s[j].y,-1); 
		} else {
			sq.push(s[j].y);
		}
		j++;
	}	
}
int main(){
	scanf("%d%d",&n,&m);
	int u;
	for (int i=1;i<=n;i++) {
		scanf("%d",&u);
		s[i] = pa(u,i);
		add(i,1);
	}
	ll times = 0;
	sort(s+1,s+1+n);
	for (int i=1,j=1;i<=n;i++) {
		if (nq.size() == 0 && s[j].x > times) 
			times = s[j].x;
		to_queue(j, times);
		int id = nq.front(); nq.pop();
		times += m, ret[id] = times;
		to_queue(j, times);
		add(id,1);
		if (!sq.empty() && get_sum(sq.top()) == sq.top()) {
			int now = sq.top();
			nq.push(now); add(now,-1);
			sq.pop(); 
		} 
	}
	for (int i=1;i<=n;i++)
		printf("%lld ",ret[i]);
	return 0;
}

F - Catowice City

一個結論就是人和貓的編號一定是互補的,這個由第i個人肯定和第i只貓有連邊推出

然後就是建邊找出度爲0的強連通分量

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int mx = 2e6 + 10;
int n,m;
bool vis[mx];
int sta[mx],siz,is;
int dfn[mx],id[mx];
int be[mx],ty;
vector <int> g[mx];
void tarjan(int u) {
	dfn[u] = id[u] = ++is;
	sta[++siz] = u;
	vis[u] = 1;
	for (int v:g[u]) {
		if (!dfn[v]) {
			tarjan(v);
			id[u] = min(id[u],id[v]);
		} else if (vis[v])
			id[u] = min(id[u],dfn[v]);
	}
	if (id[u]==dfn[u]) {
		ty++;
		while (sta[siz] != u) {
			be[sta[siz]] = ty;
			vis[sta[siz]] = 0;
			siz--;
		}
		be[u] = ty,vis[u] = 0,siz--;
	}
}
int cnt_one() {
	int cnt = 0;
	for (int i=1;i<=n;i++)
		if (be[i]==1) cnt++;
	return cnt;
}
int main() {
	int t;
	scanf("%d",&t);
	while (t--) {
		scanf("%d%d",&n,&m);
		for (int i=1;i<=2*n;i++) 
			g[i].clear();
		ty = is = siz = 0;
		for (int i=1;i<=2*n;i++)
			dfn[i] = vis[i] = 0;
		for (int i=0,u,v;i<m;i++) {
			scanf("%d%d",&u,&v);
			if (u==v) g[v+n].push_back(u);
			else g[u].push_back(v+n);
		}
		if (n == 1) {
			puts("No");
			continue;
		}
		for (int i=1;i<=n;i++) if(!dfn[i])
			tarjan(i);
		int cnt = cnt_one();
		if (cnt == n) puts("No");
		else {
			//cout << cnt  << endl;
			puts("Yes");
			printf("%d %d\n",cnt,n-cnt);
			for (int i=1;i<=n;i++) if (be[i]==1)
				printf("%d ",i);
			puts("");
			for (int i=1;i<=n;i++) if (be[i]!=1)
				printf("%d ",i);
			puts("");
		}
	}
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章