月【贪心 构造 人类智慧】

题意

小 X 和小 Q 在海边捡贝壳。

小 X 把捡到的贝壳分为三类。小 Q 趁小 X 不注意,把贝壳分到了 \(n\) 个袋子里,其中第 个袋子中三类贝壳的数量分别为 \(x_i,y_i,z_i\)

为了安慰小 X,小 Q 让小 X 先选 \(\lceil \frac{n}{2} \rceil +1\) 袋贝壳走,剩下的就都归小 Q 了。

小 X 想请你帮助她,找到一种选贝壳的方案,使得她每一类贝壳都不比小 Q 拿到的少。

输入

第一行一个正整数 \(n\)

接下来 \(n\) 行,每行三个非负整数 \(x_i,y_i,z_i\)

输出

若无解,则输出一行 No

若有解,第一行输出 Yes。第二行输出 \(\lceil \frac{n}{2} \rceil +1\) 个数,表示选的袋子的编号。你需要保证选的编号合法且互不相同。

范围

对于 \(100\%\) 的数据,保证 \(2\leq n\leq 10^5,x_i,y_i,z_i\leq 10^9\)

思路

不难猜出答案一定是 Yes

首先偶数情况肯定是比奇数情况强的,因此对于 \(n\) 为奇数的情况,我们补充一组 \((0,0,0)\) 使之成为偶数。

\(n=2m\),则我们可以取 \(m+1\) 个数。

我们先将 \(2m\) 个数按 \(x_i\) 从小到大排序,然后取出 \((x_{2m},y_{2m},z_{2m})\)

再将剩下的 \(2m-1\) 个数按 \(y_i\) 从小到大排序,然后取出 \((x_{2m-1},y_{2m-1},z_{2m-1})\)

考虑剩下的 \(2m-2\) 个数,我们还可以取 \(m-1\) 个,恰好是一半,于是可以考虑两两配对。

\(2m-2\)​ 个数按 \(x_i\)​ 排序,则 \(x_1\leq x_2\leq x_3\leq \dots\leq x_{2m-2}\)​。将相邻两个分为一组,共 \(m-1\)​ 组。

在这 \(m-1\) 组中每组取一个,则最终 \(x\) 的和为 \(x_1+x_3+x_5+\dots+x_{2m-3}+x_{2m-1}+x_{2m}\)

注意到 \(x_3\geq x_2,x_5\geq x_4,\dots,x_{2m-3}\geq x_{2m-4},x_{2m}\geq x_{2m-2}\)

则有 \(x_1+x_3+x_5+\dots+x_{2m-3}+x_{2m-1}+x_{2m} \geq x_1 + x_2 + x_4+\dots+x_{2m-4}+x_{2m-1}+x_{2m-2}\)​​。

此时显然有取得数不小于剩下的数。

同理,我们按 \(y_i\) 排序,两两分组。

对于这两种排序方式,我们将同一组的两个点连一条边,表示两个点只能选一个。

每个点度数为 \(2\),且每个点连出去的两条边颜色不同,则最后的图是若干个偶环。

对于每个偶环,我们取 \(z\) 较大的一半即可。

注意若选了对 \(n\) 为奇数的情况新加的点,要去掉并任选一个没选的点,显然一定不会更劣。

效率 \(O(n\log n)\)

代码

点击查看代码
#include<bits/stdc++.h>
#define R register int
#define I inline
#define ll long long
using namespace std;
const int bufsz=1<<20;
char buf[bufsz],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,bufsz,stdin),p1==p2)?0:*p1++)
I int read()
{
	char ch=GC;int x=0;
	while(ch<'0'||ch>'9')ch=GC;
	while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=GC;}
	return x;
}
const int N=1e5+3;
struct edge{int to,nxt;}e[N<<1];
int lst[N],tt;
I void link(int u,int v)
{
	e[++tt].to=v;
	e[tt].nxt=lst[u];
	lst[u]=tt;
}
int a[N],b[N],c[N],t[N];
I bool cmpa(int x,int y){return a[x]<a[y];}
I bool cmpb(int x,int y){return b[x]<b[y];}
int ret[N],tp;
vector<int>p[2];
ll s[2];
bool vs[N];
void dfs(int u,bool w)
{
	if(vs[u])return;vs[u]=1;
	s[w]+=c[u];p[w].push_back(u);
	for(R i=lst[u];i;i=e[i].nxt)dfs(e[i].to,!w);
}
int main()
{
	int n=read(),m=-1;
	for(R i=1;i<=n;i++)a[i]=read(),b[i]=read(),c[i]=read(),t[i]=i;
	if(n&1)++n,m=t[n]=n;
	sort(t+1,t+n+1,cmpa);ret[++tp]=t[n--];
	sort(t+1,t+n+1,cmpb);ret[++tp]=t[n--];
	for(R i=1;i<=n;i+=2)link(t[i],t[i+1]),link(t[i+1],t[i]);
	sort(t+1,t+n+1,cmpa);
	for(R i=1;i<=n;i+=2)link(t[i],t[i+1]),link(t[i+1],t[i]);
	for(R i=1;i<=n;i++)
	{
		if(vs[t[i]])continue;
		s[0]=s[1]=0;
		p[0].clear();p[1].clear();
		dfs(t[i],0);
		bool k=s[0]<s[1];
		for(auto u:p[k])
		{
			if(u==m)ret[++tp]=p[!k][0];
			else ret[++tp]=u;
		}
	}
	puts("Yes");
	for(R i=1;i<=tp;i++)printf("%d ",ret[i]);
	return 0;
}
posted @ 2021-10-18 21:37  nkxjlym  阅读(64)  评论(0)    收藏  举报