首页 > 其他分享 >题解 P7971【[KSN2021] Colouring Balls】

题解 P7971【[KSN2021] Colouring Balls】

时间:2023-07-25 09:55:40浏览次数:59  
标签:10 cnt Balls 颜色 测试点 int 题解 P7971 query

posted on 2022-10-08 19:07:28 | under 题解 | source

problem

交互库有一个长为 \(n\) 的颜色序列,你可以询问区间 \([l,r]\) 中有多少种颜色,最后还原交互库手中的序列,只需要保持相对顺序不变。\(n\leq 10^3\),最多询问次数 \(Q=2000\) 或 \(Q=10^4\)。

solution

令 \(C\) 为 \([1,n]\) 的颜色种类数,一开始就 \(query(1,n)\) 一次。

\(C=1,C=n\):\(Q=O(1)\)

相同颜色连续:\(Q=O(n)\)

做一个类似于去重的工作,把相邻两个颜色相同的(\(query(i-1,i)=1\))合并成同一种颜色。因为相同颜色连续,所以不需要考虑其它,这样就能通过 \(T\leq 2\) 的测试点。

\(C=3\):\(Q=O(n)\)

考虑先去重,去掉相邻的相同颜色。对于连续的 \(a,b,c\) 的颜色块,如果

  • \(query(a,c)=1\),这可能吗?
  • \(query(a,c)=2\),可以推出 \(a\) 的颜色和 \(c\) 的颜色相同。
  • \(query(a,c)=3\),这三个颜色互不相同,假设我们已经知道 \(a,b\) 的颜色,那么 \(c\) 就是异于它们的第三种颜色。实现时暴力找出 \([1,b]\) 中有什么颜色,最后去掉 \(a,b\),剩下的就是 \(c\) 的颜色(如果没有说明 \(c\) 是新颜色)。

这样就能通过 \(T=3\) 的测试点。

\(C=n-1\):\(Q=O(n)\)

因为 \(C=n-1\),所以一定存在一对 \(i,j\) 使得这两个下标的颜色相同。

考虑一个包含了 \([i,j]\) 的区间,这一段区间里一定有 \(len-1\) 种颜色。那么令 \(l=1,r=n\),让 \(l\) 一直往右扫,\(r\) 一直往左扫,什么时候 \(query(l,r)=r-l+1\),那么就找到了 \(i,j\)。这样就通过了 \(T=5\) 的测试点

通解:\(Q=O(n\log n)\)

考虑一遍扫过去,用 \([1,i-1]\) 的颜色求出 \(i\) 的颜色。

对于 \(i\),假设我们有一个编号 \(k\):

  • 若 \(query(k,i)=query(k,i-1)\),说明 \(i\) 的颜色一定是 \([k,i-1]\) 中的其中一种;
  • 若 \(query(k,i)=query(k,i-1)+1\),说明 \(i\) 的颜色是 \([k,i-1]\) 中的其中一种,它可能是 \([1,k-1]\) 的其中一种,或者是一种不同于 \([1,i-1]\) 的全新的颜色。

发现 \(query(k,i)\) 有单调性,试图二分 \(k\in[1,i-1]\),于是你解决了 \(T=6\) 和 \(T=7\) 的测试点。

\(Q=O(n\log C)\) 及小优化

动态维护一个 \(pre_c\) 表示颜色为 \(c\) 的最大的编号,这样,\(query(k,i-1)\) 就等同于有多少个 \(pre_c\) 落在 \([k,i-1]\) 中。把所有有意义的 \(pre_c\) 的值拉出来排序(容易发现只有 \(O(C)\) 个),对着排序的 \(pre\) 二分,那么就能通过 \(T=3\) 的测试点。注意到因为 \(n\leq 10^3\),所以排序部分直接写 \(O(n^2+n\cdot C \log C))\) 的时间复杂度也能过。

还不能通过 \(T=4\) 的测试点,因为这样每个颜色需要询问 \(3\) 次,需要优化。这个优化很简单:如果 \(\color{red}{C}=4\)(而不是 \(T=4\)),当前有意义的 \(pre\) 有 \(C\) 个,那么不需要特判 \(i\) 是新颜色的情况,这是不可能的,询问次数降为 \(2\) 次(若 \(pre\) 有 \(3\) 个那么只需要询问 \(2\) 次)。于是可以通过 \(T=4\) 的测试点。

code

实现时可以用并查集。

#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template<int N> struct dsu{
	int fa[N+10],siz[N+10],cnt;
	dsu(int n=N):cnt(n){for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1;}
	int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	void merge(int x,int y){
		if(x=find(x),y=find(y),x!=y){
			if(siz[x]<siz[y]) swap(x,y);
			cnt--,siz[x]+=siz[y],fa[y]=x;
		}
	}
};
int n,T,f[1010][1010],last[1010],p[1010];
dsu<1010> s;
int query(int l,int r){
	if(l>r) swap(l,r);
	if(f[l][r]==-1){
		printf("? %d %d\n",l,r);
		fflush(stdout);
		scanf("%d",&f[l][r]);
	}
	return f[l][r];
}
int flower(){
	int cnt=0;
	p[++cnt]=1;
	for(int i=2;i<=n;i++){
		if(query(p[cnt],i)==1) s.merge(p[cnt],i);
		else p[++cnt]=i;
	}
	return cnt;
}
int main(){
	memset(f,-1,sizeof f);
	scanf("%d%d%*d",&T,&n);
	if(T==1||T==2) flower();
	else if(query(1,n)==n-1){
		int L=1,R=n;
		while(query(n,L)==n-L) L++;
		while(query(R,1)==R-1) R--;
		s.merge(L-1,R+1);
	}else if(query(1,n)==3){
	    int cnt=flower();
	    if(query(p[1],p[3])==2) s.merge(p[1],p[3]);
		for(int i=4;i<=cnt;i++){
			if(query(p[i-2],p[i])==2) s.merge(p[i-2],p[i]);
			else{
				set<int> fs;
				for(int j=1;j<i;j++) fs.insert(s.find(p[j]));
				fs.erase(s.find(p[i-1]));
				fs.erase(s.find(p[i-2]));
				if(!fs.empty()) s.merge(*fs.begin(),p[i]);
			}
		}
	}else if(query(1,n)!=n){
		for(int i=1;i<=n;i++){
			int cnt=0;
			for(int j=1;j<=1000;j++) if(last[j]) p[++cnt]=last[j];
			sort(p+1,p+cnt+1);
			int L=1,R=cnt;
			while(L<R){
				int mid=(L+R+1)>>1;
				if(query(p[mid],i)==cnt-mid+1) L=mid;
				else R=mid-1;
			}
			if(query(1,n)==cnt||!cnt||query(p[L],i)==cnt-L+1) s.merge(p[L],i);
			last[s.find(i)]=i;
		}
	}
	printf("! ");
	for(int i=1;i<=n;i++) printf("%d%c",s.find(i)," \n"[i==n]);
	fflush(stdout);
	return 0;
}
/*
1213
*/

标签:10,cnt,Balls,颜色,测试点,int,题解,P7971,query
From: https://www.cnblogs.com/caijianhong/p/solution-P7971.html

相关文章

  • CF1051G Distinctification题解
    link首先可以发现,题目给定的两种操作为我们提供了“反悔机制”,所以有:结论\(1\):即任何一个可以到达的局面都能到达最优解。利用这个结论,首先我们先去重。继续提炼性质,与相差不到\(1\)的数为基准\(+1\)与\(-1\)操作,将这个数的变化范围限制在了一个区间,并且这个区间的数能......
  • 题解 Codeforces Round 887 (Div 1+Div 2) / CF1853AB,CF1852ABCD
    下大分!悲!Div1只过了1A!!!但还是补完整场Div2吧。A.Desortinghttps://codeforces.com/problemset/problem/1853/Aproblem用操作:\([1,i]++,[i+1,n]--\),使得数组不单调不降,求最小操作次数。\(n\leq10^5\)。solution操作等同于在差分数组上选出\(i\),做\(c_1:=c_1+1,c_i:......
  • UOJ #284. 快乐游戏鸡题解(长链剖分+单调栈合并)
    UOJ#284.快乐游戏鸡题解(长链剖分+单调栈合并)题面一番战斗之后,程序猿被计算鸡们赶走了。随着垫子计算鸡一声令下:“追!”,于是计算鸡村全村上下开始乘胜追击。计算鸡们希望在新的一年到来之际给程序猿以重创,出掉这一年的恶气。可是程序猿一追就走,一走就跑,一跑就无影无踪。计算鸡......
  • 洛谷CF1738C题解
    好一道博弈论水题题目传送门更好的食用体验题目大意:给定长度为$n$的数列$a_1,a_2,\dots,a_n$,两名玩家Alice、Bob依次以最优策略从数列中取走一个数,Alice先取,直至为空博弈结束。若Alice取走的所有数之和为偶,Alice胜利;若Alice取走的所有数之和为奇,Bob胜利......
  • 【题解】Imbalanced Arrays - Codeforces 1852B
    出处:CodeforcesRound887链接:https://codeforces.com/problemset/problem/1852/B题目大意:给定一个包含\(n\)个非负整数的频次序列\(f\)。构造任意一个等长的整数序列\(b\),要求①\(b\in[-n,n]\)but$b\neq0$②\(b\)中不存在相反数③对于每个坐标\(i\)......
  • 【P8302 题解】
    Solution设\(g(x)\)表示\(x\)的最小质因子。则\(f(x)=n+\dfrac{n}{g(x)}=\dfrac{g(x)+1}{g(x)}\timesn\)。分情况讨论:\(g(x)=2\),经过\(1\)次变换之后,\(f(x)\)增加了一个因子\(3\),减少了一个因子\(2\)。\(g(x)>2\),则满足\(g(x)\nmid2\),否则与最小质因子矛盾,......
  • 【题解】Ntarsis' Set - Codeforces 1852A
    出处:CodeforcesRound887链接:https://codeforces.com/problemset/problem/1852/A题目大意:给定一个包含\(n\)个正整数的表示删除位置的严格升序序列\(p\),以及另外一个连续正整数的被删除的无穷序列\(l\)。进行\(k\)次删除操作,每次操作从无穷序列\(l\)中同时删除位......
  • Codeforces Round 887 (Div. 1) 题解
    https://codeforces.com/contest/1852/problemsA.Ntarsis'Sethttps://codeforces.com/contest/1852/problem/A感觉不是很一眼。\(n\)和\(k\)都是\(2\times10^5\),不能暴力,设当前集合为\({1,2,\dots,10^{1000}}\),那么被操作过一次的最小值就应该是\(\text{MEX}(0,......
  • 国标GB28181视频平台LntonGBS(含源码)国标视频平台播放视频时偶尔出现播放失败的问题解
    LntonGBS是基于公安部推出的安防主流协议(国标GB28181协议)的视频接入、处理及分发平台,具有视频直播监控、云端录像、云存储、检索回放、智能告警、语音对讲等功能,能够涵盖所有监控领域的视频能力需求,已经在大量的项目中落地应用,如明厨亮灶、平安乡村、雪亮工程等。有用户反馈,在某项......
  • P7831 题解
    problem&blog。妙妙题。单杀了,来写篇题解。下文中\(ans_u\)表示从\(u\)点出发的答案。考虑直接做。发现更新任何一个点,都可能会对一堆点造成影响,\(O(n^2)\)无法接受。一些简单的性质:不能进入一个环的\(ans_u=-1\)。否则,对于\((u,v,r,p)\),\(r\)是最大的\(r\),那么只......