# Name
A Remove Smallest [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) x16658
B Gifts Fixing [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) x15673
C Boats Competition [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) x9194
D Binary String To Subsequences [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) x4757
E1 Weights Division (easy version) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) x848
E2 Weights Division (hard version) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) x210
F Yet Another Segments Subset [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) [CF1399] Codeforces Round #661 (Div. 3) 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;
}

相关文章:

  • 2019-09-07
  • 2021-12-13
  • 2021-07-23
  • 2022-01-08
  • 2021-09-09
  • 2021-05-23
  • 2021-11-08
  • 2021-07-17
猜你喜欢
  • 2022-12-23
  • 2020-05-15
  • 2022-12-23
  • 2021-09-01
  • 2021-04-06
  • 2021-05-01
相关资源
相似解决方案