1. 程式人生 > 實用技巧 >loj#2985. 「WC2019」I 君的商店

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;
	}
}