loj#2985. 「WC2019」I 君的商店

题目描述

https://loj.ac/problem/2985

太长了不写

题解

刚了几天刚出了69分加一些奇奇怪怪的做法

subtask3

首先根据0和N-1可以找到1连续段的开头,然后二分

把不确定性消掉,只需要两个一组询问即可,根据奇偶性讨论之后的和只有0和2

subtask5

首先用2N的次数找到最大值,最大值一定是1

然后对于任意两个数xy,先用2次来保证x>=y,然后3次询问x+y与1的大小关系

如果x+y>=1则x=1,否则y=0,最后剩下的一个数根据奇偶性求出来

总次数是7N

瞎搞

没有写并不知道结果怎样

在求最大值的时候启发式合并,合出来的东西是一棵深度log有N/2个叶子的树

从上往下按照树边询问,因为大小关系已经确定所以只需要3次

如果当前节点已经可以确定为1就往子树里搞,因为再搞下去可能得不到新的信息(如果某个点确定为0那么子树都是0),最后剩下的再用subtask5的做法5*个数来搞

最坏情况下剩下的都是叶子,也就是说每个非叶子节点都询问了一次,那么次数是2N+3*N/2+5*N/2=6N

从叶子开始考虑可以更优,因为一旦一个点是1那么到根的路径都是1

次数不知道是多少但是感觉查找的部分可以变成3*N/4,也就是总次数是21/4*N

subtask6

subtask5的瓶颈在于用2N次来确定1,因为M=5N+100,所以考虑不确定具体的1而是得到一个单调的序列,最后用二分解决

维护一个数a和剩余数序列,每次提出两个数xy来考虑

首先用2次保证x>=y,然后询问x+y与a的关系

如果a>=x+y那么y=0把x丢回去,否则有x>=a,把a变成x把y丢回去

把所有的a按顺序记下来,得到一个单调不减的序列和剩下的一个不确定数,用二分把数插进序列

由于max(ai,z)=1,所以得到1之后同subtask3二分确定序列

次数是5N+5log,如果不把数插进去直接二分可以做到3log但是不好写所以没写

code

#include <bits/stdc++.h>
#include "shop.h"
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
using namespace std;

void swap(int &x,int &y) {int z=x;x=y;y=z;}
void find_price(int task_id, int N, int K, int ans[]) {
	int a[100001],b[100001],c[100001],d[100001],i,j,k,l,r,mid,t1=0,t2=0,x,y,z,sum,A,t;
	bool bz;
	
	if (task_id==3)
	{
		fo(i,1,N) a[i-1]=i-1,b[N-i]=i-1;
		a[0]=0;b[0]=N-1;
		bz=query(a,1,b,1);
		
		l=1;r=(N-!K)/2-1;
		while (l<r)
		{
			mid=(l+r)/2;
			a[0]=0,b[0]=mid*2-1+(!K),b[1]=mid*2+(!K);
			if (bz)
			a[0]=(N-1)-a[0],b[0]=(N-1)-b[0],b[1]=(N-1)-b[1];
			
			if (query(a,1,b,2))
			l=mid+1; else r=mid;
		}
		a[0]=0,b[0]=l*2-1+(!K),b[1]=l*2+(!K);
		if (bz)
		a[0]=(N-1)-a[0],b[0]=(N-1)-b[0],b[1]=(N-1)-b[1];
		l-=!query(a,1,b,2);
		
		ans[0]=1;if (!K) ans[1]=1;
		fo(i,1,l) ans[i*2-1+(!K)]=ans[i*2+(!K)]=1;
		if (bz)
		{
			fo(i,1,N/2)
			swap(ans[i-1],ans[(N-i+1)-1]);
		}
	}
	else
	{
		l=N-1;
		fo(i,1,N-1) c[i]=i;A=0;t=1;d[t]=0;
		while (l>1)
		{
			x=c[l-1],y=c[l],l-=2;
			a[0]=x,b[0]=y;
			if (query(a,1,b,1)) swap(x,y);
			
			a[0]=A,b[0]=x,b[1]=y;
			if (!query(a,1,b,2))
			ans[y]=0,c[++l]=x;
			else
			A=x,c[++l]=y,d[++t]=x;
		}
		
		a[0]=c[1],b[0]=d[t];
		if (!query(a,1,b,1)) l=t+1;
		else
		{
			l=1;r=t;
			while (l<r)
			{
				mid=(l+r)/2;
				a[0]=c[1],b[0]=d[mid];
				if (!query(a,1,b,1))
				l=mid+1; else r=mid;
			}
		}
		fd(i,t+1,l+1) d[i]=d[i-1];d[l]=c[1];++t;
		
		fd(i,t/2,1) swap(d[i],d[t-i+1]);
		l=1;r=(t-1-!(K&1))/2;
		while (l<r)
		{
			mid=(l+r)/2;
			a[0]=d[1],b[0]=d[mid*2+!(K&1)],b[1]=d[mid*2+1+!(K&1)];
			if (query(a,1,b,2))
			l=mid+1; else r=mid;
		}
		if (l>r) --l;
		else
		{
			a[0]=d[1],b[0]=d[l*2+!(K&1)],b[1]=d[l*2+1+!(K&1)];
			l-=!query(a,1,b,2);
		}
		
		fo(i,1,l*2+1+!(K&1)) ans[d[i]]=1;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章