ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP2020 退役记

2020-12-05 20:34:37  阅读:170  来源: 互联网

标签:now frac int back m2 NOIP2020 退役 id


NOIP2020 退役记

把原来写的东西全删了。毕竟留下了不少遗憾,也让我自己失望了吧。

12:30 想到 T3 怎么做,写完后发现第二个样例过不去,也就爆零了。

晚上回家理顺了一遍思路,写了半个小时不到就写完并在 oitiku 上 AC 了。我刷了不少 AGC 和 CF 的构造题,原本只是准备省选和 NOI 写的,结果 NOIP 考到的。我以为我能暴切 T3 考到省队线,结果被 T3 送退役了。

估分 \(80\sim 100+84\sim 100+0+60\sim 80=224\sim 280\)。不过应该省选还是会去的,但是翻盘的可能性不大了。

不过我也努力过了,这次的失误也是我想题较慢的缘故。若是把这道 T3 放到省选或 NOI 上,我感觉自己能现场写出来的。太遗憾了,实在是太遗憾了。

要是 T3 一点都不会做该多好,这样我就可以安心退役了。我真的心有不甘啊啊啊啊啊啊。

唉,在绝望中给人希望是一件多么残酷的事情。

T3 做法:

考虑分治,将颜色编号 \(\le mid\) 和 \(>mid\) 分为两个集合。这样问题转化为只用若干个长度为 \(m\) 的 \(01\) 串,将要求每个串全部 \(0/1\)。

接着考虑两个串 \(S,T\)。可以知道,\(cnt_{S,0/1}+cnt_{T,0/1}\) 总有一个 \(\ge m\)。那么,我们可以通过如下构造,得到一个串全部 \(0/1\)。

设空串为 \(now\)。取 \(S,T\) 的后 \(\lfloor \frac m2\rfloor\) 位,放到 \(now\) 中。如果是 \(0\) 放到 \(S\),\(1\) 放到 \(T\),那么可以得到一个长为 \(\lfloor \frac m2\rfloor\) 的串全部 \(0/1\)。若是 \(S\),再将 \(S\) 全部放到 \(now\)。此时 \(S\) 为空串,\(T\) 没有性质,\(now\) 前 \(\lfloor \frac m2\rfloor\) 位相等。此处用了 \(3m\) 次操作。

对于串 \(now\) 和 \(T\),我们取 \(now\) 的后 \(\lceil \frac m2\rceil\) 位,\(T\) 的后 \(\lfloor \frac m2\rfloor\) 位,执行类似刚才的操作。此时 \(now\) 的后 \(\lceil \frac m2\rceil\) 位相等。此处用了 \(2m\) 次操作。

现在讨论 \(now\) 前 \(\lfloor \frac m2\rfloor\) 位和后 \(\lceil \frac m2\rceil\) 位是否相等。若相等,那么我们已经构造了出来。否则,将 \(now\) 的后 \(\lceil \frac m2\rceil\) 位放到 \(S\),然后对 \(T\) 执行刚才的过程。如果是 \(0\) 放到 \(S\),\(1\) 放到 \(now\)。这样 \(S/now\) 一定有一个串符合条件,用了 \(C\in (6m,7m)\) 次操作。

上界大概是 \(O(F(n)\times 7m)\),\(F(n)=\sum (len_{rt}-1)\),\(rt\in\) 长度为 \(n\) 的线段树。\(F(50)=237\),可以放心写,不怎么卡常数。

#include <bits/stdc++.h>
using namespace std;
const int maxn=55;
const int maxa=820005;
int n,m,x_[maxa],y_[maxa],sz,now;
vector<int> g[maxn];
inline void add(int x,int y)
{
	x_[++sz]=x,y_[sz]=y;
	g[y].push_back(g[x].back());
	g[x].pop_back();
}
void solve(int l,int r,vector<int> &id)
{
	if(id.size()==1) return;
	int mid=(l+r)>>1;
	vector<int> A,B; A.clear(),B.clear();
	while(!id.empty())
	{
		int s=id.back(); id.pop_back();
		int t=id.back(); id.pop_back();
		// s, t -> now
		for(int i=0;i<m/2;i++) add(s,now),add(t,now);
		int pa=0,pb=0;
		for(int i=0;i<g[now].size();i++)
			if(g[now][i]<=mid) pa++;
			else pb++;
		int op1=(pa>=m/2)?0:1;
		while(!g[now].empty())
		{
			if(((op1==0 && g[now].back()<=mid) || (op1==1 && g[now].back()>mid)) && g[s].size()<m) add(now,s);
			else add(now,t);
		}
		for(int i=0;i<m;i++) add(s,now);
		for(int i=0;i<m/2;i++) add(t,s);
		for(int i=0;i<(m+1)/2;i++) add(now,s);
		int qa=0,qb=0;
		for(int i=0;i<g[s].size();i++)
			if(g[s][i]<=mid) qa++;
			else qb++;
		int op2=(qa>=(m+1)/2)?0:1;
		while(!g[s].empty())
		{
			if(((op2==0 && g[s].back()<=mid) || (op2==1 && g[s].back()>mid)) && g[now].size()<m) add(s,now);
			else add(s,t);
		}
		if((g[now][0]<=mid)==(g[now].back()<=mid))
		{
			if(g[now].back()<=mid) A.push_back(now);
			else B.push_back(now);
			if(id.empty())
			{
				if(g[t].back()<=mid) A.push_back(t);
				else B.push_back(t);
			}
			else id.push_back(t);
			now=s;
		}
		else
		{
			// op1 -> now, op2 -> s
			for(int i=0;i<(m+1)/2;i++) add(now,s);
			int x=0,y=0;
			for(int i=0;i<g[t].size();i++)
				if(g[t][i]<=mid) x++;
				else y++;
			if(op2==0)
			{
				if(x+g[s].size()>=m)
				{
					while(!g[t].empty())
					{
						if(g[t].back()<=mid && g[s].size()<m) add(t,s);
						else add(t,now);
					}
					A.push_back(s);
					if(id.empty())
					{
						if(g[now].back()<=mid) A.push_back(now);
						else B.push_back(now);
					}
					else id.push_back(now);
					now=t;
				}
				else
				{
					while(!g[t].empty())
					{
						if(g[t].back()>mid && g[now].size()<m) add(t,now);
						else add(t,s);
					}
					B.push_back(now);
					if(id.empty())
					{
						if(g[s].back()<=mid) A.push_back(s);
						else B.push_back(s);
					}
					else id.push_back(s);
					now=t;
				}
			}
			else
			{
				if(y+g[s].size()>=m)
				{
					while(!g[t].empty())
					{
						if(g[t].back()>mid && g[s].size()<m) add(t,s);
						else add(t,now);
					}
					B.push_back(s);
					if(id.empty())
					{
						if(g[now].back()<=mid) A.push_back(now);
						else B.push_back(now);
					}
					else id.push_back(now);
					now=t;
				}
				else
				{
					while(!g[t].empty())
					{
						if(g[t].back()<=mid && g[now].size()<m) add(t,now);
						else add(t,s);
					}
					A.push_back(now);
					if(id.empty())
					{
						if(g[s].back()<=mid) A.push_back(s);
						else B.push_back(s);
					}
					else id.push_back(s);
					now=t;
				}
			}
		}
	}
	solve(l,mid,A),solve(mid+1,r,B);
}
int main()
{
	freopen("ball.in","r",stdin);
	freopen("ball.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			int x; scanf("%d",&x);
			g[i].push_back(x);
		}
	vector<int> id; id.clear();
	for(int i=1;i<=n;i++) id.push_back(i);
	now=n+1,solve(1,n,id);
	printf("%d\n",sz);
	for(int i=1;i<=sz;i++)
		printf("%d %d\n",x_[i],y_[i]);
	return 0;
}

标签:now,frac,int,back,m2,NOIP2020,退役,id
来源: https://www.cnblogs.com/owencodeisking/p/14090813.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有