[CF1399] Codeforces Round #661 (Div. 3)


# Name
A Remove Smallest Submit Add to favourites img x16658
B Gifts Fixing Submit Add to favourites img x15673
C Boats Competition Submit Add to favourites img x9194
D Binary String To Subsequences Submit Add to favourites img x4757
E1 Weights Division (easy version) Submit Add to favourites img x848
E2 Weights Division (hard version) Submit Add to favourites img x210
F Yet Another Segments Subset Submit Add to favourites img x126

A

Code:

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define rint register int
using namespace std;
const int N=56;
int T;
int n;
int a[N];
int main()
{
//	freopen("1.in","r",stdin);
	int i;
	scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		for(i=1;i<=n;i++) 
			scanf("%d",&a[i]);
		sort(a+1,a+n+1);
		for(i=2;i<=n;i++) 
			if(a[i]-a[i-1]>1) break;
		if(i==n+1) puts("YES");
		else puts("NO");
	}
	return 0;
}

B

Code:

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define rint register int
using namespace std;
const int INF=2e9+5,N=56;
int T,n;
int a[N],b[N];
int mina,minb;
LL ans;
int main()
{
//	freopen("1.in","r",stdin);
	int i;
	scanf("%d",&T);
	while(T--) {
		mina=minb=INF; ans=0;
		scanf("%d",&n);
		for(i=1;i<=n;i++) 
			scanf("%d",&a[i]),mina=min(a[i],mina);
		for(i=1;i<=n;i++)
			scanf("%d",&b[i]),minb=min(b[i],minb);
		for(i=1;i<=n;i++) 
			ans+=(LL)max(b[i]-minb,a[i]-mina);
		printf("%lld\n",ans);
	}
	return 0;
}

C

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define rint register int
using namespace std;
const int N=256,INF=1e9;
int T,n;
int w[N],cnt[N];
int main()
{
//	freopen("1.in","r",stdin);
	int i,j;
	int x;
	scanf("%d",&T);
	int res,ans;
	while(T--) {
		ans=-INF;
		scanf("%d",&n);
		for(i=1;i<=n;i++)
			scanf("%d",&w[i]);
		for(i=2;i<=(n<<1);i++) {
			memset(cnt,0,sizeof cnt);
			res=0;
			for(j=1;j<=n;j++) 
				cnt[w[j]]++;
			for(j=1;i-j>=1;j++) {
				if(cnt[j]==0) continue;
				if(i-j==j) {
					res+=cnt[j]/2;
					cnt[j]=cnt[j]%2;
				}
				else {
					x=min(cnt[j],cnt[i-j]);
					res+=x;
					cnt[j]-=x; cnt[i-j]-=x;
				}	
			}
			ans=max(ans,res);
		}
		printf("%d\n",ans);
	}
	return 0;
}

D

Code:

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define rint register int
using namespace std;
const int N=2e5+5;
int a[N];
char c[N];
int T,n;
struct DSU
{
	int par[N];
	int Find(int x)	
	{
		if(x==par[x]) return x;
		else return par[x]=Find(par[x]);
	}
	inline void reset(int n)
	{
		for(int i=1;i<=n+4;i++) 
			par[i]=i;
		return;
	}
}b0,b1;
int d[N];
void draw(int now,int col)
{
	if(now>n) return;
	d[now]=col;
	if(a[now]==0) {
		b0.par[now]=b0.Find(now+1);
		draw(b1.Find(now),col);
	} 
	else {
		b1.par[now]=b1.Find(now+1);
		draw(b0.Find(now),col);
	}
	return;
}
int main()
{
//	freopen("1.in","r",stdin);
	int i;
	int ans;
	scanf("%d",&T);
	while(T--) {
		ans=0;
		scanf("%d",&n);
		fill(d,d+n+2,0);
		scanf("%s",c+1);
		for(i=1;i<=n;i++) 	
			a[i]=c[i]-'0';
		b0.reset(n); b1.reset(n);
		for(i=n;i>=1;i--) {
			if(a[i]==1) b1.par[i]=i,b0.par[i]=b0.par[i+1];
			else b1.par[i]=b1.par[i+1],b0.par[i]=i;
		}
		for(i=1;i<=n;i++) {
			if(d[i]>0) continue;
			d[i]=++ans;
			draw(i,ans);
		}
		printf("%d\n",ans);
		for(i=1;i<=n;i++) 
			printf("%d ",d[i]);
		printf("\n");
	}
	return 0;
}

E

都是貪心+分類討論。

E1

Code:

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define rint register int
using namespace std;
const int N=2e5+5;
int one[N];
int ver[N],Next[N],idx;
LL edge[N];
inline void AddEdge(int a,int b,LL c)
{
	Next[++idx]=one[a];
	one[a]=idx;
	ver[idx]=b;
	edge[idx]=c;
	return;
}
//==================================
LL sum[N];
int T,n;
LL S;
LL ss,ans;
priority_queue< pair<LL,int> > q;
void dfs(int x,int fa)
{
	sum[x]=0;
	int i;
	for(i=one[x];i>0;i=Next[i]) {
		if(ver[i]!=fa) 
			dfs(ver[i],x),sum[x]+=sum[ver[i]];
	}
	for(i=one[x];i>0;i=Next[i]) {
		if(ver[i]==fa) continue;
		q.push(make_pair(sum[ver[i]]*(edge[i]-edge[i]/2),i));
		ss+=sum[ver[i]]*edge[i];
	}
	if(ver[one[x]]==fa&&Next[one[x]]==0) 
		sum[x]=1;
	return;
}
int main()
{
//	freopen("1.in","r",stdin);
	int i;
	int x,y;
	LL z;
	scanf("%d",&T);
	while(T--) {
		while(q.size()) q.pop();
		ss=0; ans=0;
		scanf("%d%lld",&n,&S);
		idx=0;
		fill(one,one+n+2,0);
		fill(ver,ver+2*n+2,0);
		fill(Next,Next+2*n+2,0);
		fill(edge,edge+2*n+2,0);
		for(i=1;i<=n-1;i++) {
			scanf("%d%d%lld",&x,&y,&z);
			AddEdge(x,y,z);
			AddEdge(y,x,z);
		}
		dfs(1,0);
		while(ss>S) {
			x=q.top().second; z=q.top().first;
			q.pop(); ans++;
			ss-=z;
			edge[x]=edge[x]/2;
			q.push(make_pair(sum[ver[x]]*(edge[x]-edge[x]/2),x));
		}
		printf("%lld\n",ans);
	}
	return 0;
}

E2

Code:

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define rint register int
using namespace std;
const int N=2e5+5;
int one[N];
int ver[N],Next[N],coin[N],idx;
LL edge[N];
inline void AddEdge(int a,int b,LL c,int d)
{
	Next[++idx]=one[a];
	one[a]=idx;
	ver[idx]=b;
	edge[idx]=c;
	coin[idx]=d;
	return;
}
//==================================
LL sum[N];
int T,n;
LL S;
LL ss,ans;
priority_queue< pair<LL,int> > q1,q2;
void dfs(int x,int fa)
{
	sum[x]=0;
	int i;
	for(i=one[x];i>0;i=Next[i]) {
		if(ver[i]!=fa) 
			dfs(ver[i],x),sum[x]+=sum[ver[i]];
	}
	for(i=one[x];i>0;i=Next[i]) {
		if(ver[i]==fa) continue;
		if(coin[i]==1)
			q1.push(make_pair(sum[ver[i]]*(edge[i]-edge[i]/2),i));
		else q2.push(make_pair(sum[ver[i]]*(edge[i]-edge[i]/2),i));
		ss+=sum[ver[i]]*edge[i];
	}
	if(ver[one[x]]==fa&&Next[one[x]]==0) 
		sum[x]=1;
	return;
}
void clear()
{
	while(q1.size()) q1.pop();
	while(q2.size()) q2.pop();
	ss=0; ans=0;
	idx=0;
	fill(one,one+n+2,0);
	fill(ver,ver+2*n+2,0);
	fill(Next,Next+2*n+2,0);
	fill(edge,edge+2*n+2,0);
	fill(coin,coin+2*n+2,0);
	return;
}
int main()
{
//	freopen("1.in","r",stdin);
	int i;
	int x,y;
	LL z;
	int ww;
	LL z1,z2;
	LL k;
	scanf("%d",&T);
	while(T--) {
		scanf("%d%lld",&n,&S);
		clear();
		for(i=1;i<=n-1;i++) {
			scanf("%d%d%lld%d",&x,&y,&z,&ww);
			AddEdge(x,y,z,ww);
			AddEdge(y,x,z,ww);
		}
		dfs(1,0);
		while(ss>S) {
			if(q1.size()>0&&ss-q1.top().first<=S) {
				ans++;
				break;
			}
			if(q1.size()==0) {
				ww=q2.top().second; z=q2.top().first;
				ans+=2;
				ss-=z;
				edge[ww]=edge[ww]/2;
				q2.pop();
				q2.push(make_pair(sum[ver[ww]]*(edge[ww]-edge[ww]/2),ww));	
				continue;
			}
			if(q2.size()==0) {
				x=q1.top().second; z1=q1.top().first;
				ans++;
				ss-=q1.top().first;
				q1.pop();
				edge[x]=edge[x]/2;
				q1.push(make_pair(sum[ver[x]]*(edge[x]-edge[x]/2),x));	
				continue;
			}
			if(q1.size()==1) {
				ww=q2.top().second; z=q2.top().first;
				x=q1.top().second; z1=q1.top().first;
				z1+=(edge[x]/2-edge[x]/2/2)*sum[ver[x]];
				if(z>z1) {
					ans+=2;
					ss-=z;
					edge[ww]=edge[ww]/2;
					q2.pop();
					q2.push(make_pair(sum[ver[ww]]*(edge[ww]-edge[ww]/2),ww));	
				}
				else {
					ans++;
					ss-=q1.top().first;
					q1.pop();
					edge[x]=edge[x]/2;
					q1.push(make_pair(sum[ver[x]]*(edge[x]-edge[x]/2),x));	
				}
				continue;
			}
			ww=q2.top().second; z=q2.top().first;
			
			x=q1.top().second; z1=q1.top().first; q1.pop();
			y=q1.top().second; z2=q1.top().first;
			
			k=z1+(edge[x]/2-edge[x]/2/2)*sum[ver[x]];
			if(z>z1+z2&&z>k) {
				ans+=2;
				ss-=z;
				edge[ww]=edge[ww]/2;
				q2.pop();
				q2.push(make_pair(sum[ver[ww]]*(edge[ww]-edge[ww]/2),ww));	
				q1.push(make_pair(z1,x));
			}
			else {
				ans++;
				ss-=z1;
				edge[x]=edge[x]/2;
				q1.push(make_pair(sum[ver[x]]*(edge[x]-edge[x]/2),x));	
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

F

Update 2021.3.12:終於補完題了 嗚嗚嗚。

題意:給你 \(n\) 個線段,每個線段用左右端點 \(l_i,r_i\) 表示。 現在要你從中選出盡量多的線段,使得他們兩兩之間要么完全不相交,要么其中一個完全包含另一個。

同一個查詢的所有線段中保證沒有兩個線段是完全一樣的.

\(\sum n\le3000\)

翻譯來自 luogu。

思考選出線段間的關系:要么包含,要么不交。

假設有 \(u\) 包含 \(v_1,v_2...\) ,那么顯然只要 \(v_1,v_2,,,\) 自己不交或包含,並且 \(u\) 與外界的線段不交即可。

由此,我們發現這是一個子問題,即 \(u\) 包含的線段中 兩兩不交或包含 的線段的最大數量。不妨定義這個值為 \(u\) 的附加值 \(g[u]\)

考慮按線段長度從小到大 dp。

假設現在對 \(u\) dp,則把 \(v_1,v_2...\)\(l\) 排序,

\(f[i]\) 表示前 \(i\) 個並且以 \(v_i\) 結尾的最大數量,有

\[f[i]=\max_{r_j<l_i}\{f[j]\}+g[i] \]

直接做是 \(\mathcal O(n^2)\) 的,做 \(n\) 次,共 \(\mathcal O(n^3)\)

考慮優化,我們發現由於按 \(l_i\) 排序,決策集合 \(S\) 是單調不減的,

\(cmax=\max_{j \in S}\{f[j]\}\),可以用堆維護 \(r_j\) 的最小值,當 \(r_j<l_i\) 時加入 \(S\)

可以做到 \(\mathcal O(n \log n)\) ,總共 \(\mathcal O(n^2 \log n)\)

Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=5000+5;

int T,n;
PII a[N];
int b[N],cnt;
int g[N]; // g[i] 表示線段 i 的附加值。

inline bool cmplen(const PII& a,const PII& b) { return a.second-a.first<b.second-b.first; }
inline bool cmps(const int& x,const int& y) { return a[x].first<a[y].first; }
priority_queue<PII,vector<PII>,greater<PII> > q;

int main()
{
//	freopen("1.in","r",stdin);
	int i,j;
	
	scanf("%d",&T);
	while(T--) {
		memset(g,0,sizeof g);
		scanf("%d",&n);
		for(i=1;i<=n;i++) 
			scanf("%d%d",&a[i].first,&a[i].second);
		a[++n]=PII(0,2e5+1);
		sort(a+1,a+n+1,cmplen);
		for(i=1;i<=n;i++) {
			cnt=0;
			for(j=1;j<i;j++) {
				if(a[i].first<=a[j].first && a[j].second<=a[i].second) 
					b[++cnt]=j;
			}
			
			sort(b+1,b+cnt+1,cmps);
			int cmax=0;
			for(j=1;j<=cnt;j++) {
				for(;q.size() && q.top().first<a[b[j]].first;q.pop()) 
					cmax=max(cmax,q.top().second);
				q.push(PII(a[b[j]].second,cmax+g[b[j]]));
			}
			g[i]=1;
			for(;q.size();q.pop()) 
				g[i]=max(g[i],q.top().second+1); 
		}
		printf("%d\n",g[n]-1);
	}
	return 0;
}


免責聲明!

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



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