[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;
}
posted @ 2020-08-06 00:52  cjlworld  阅读(548)  评论(0编辑  收藏  举报