1. 程式人生 > 資訊 >美國初創公司 Aquarian Space 計劃在月球上覆蓋 Wi-Fi 網路:承諾速度高達 100Mbps

美國初創公司 Aquarian Space 計劃在月球上覆蓋 Wi-Fi 網路:承諾速度高達 100Mbps

\(\text{Solution}\)

發現大於中位數的數的個數是大於或等於小於中位數的個數的,所以就可以二分答案。
把大於等於\(mid\)的數變成\(1\),其餘變為\(-1\)
用主席樹儲存在每個不同\(mid\)下樹的形態,這樣我們只需維護區間的字首,字尾最大值和區間和即可。

\(\text{Code}\)

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int N = 2e4 + 5;
int size,n,rt[N],m;
LL q[5],ans;

struct nd{LL z;int id;}a[N];
struct tree{int lz,rz,z,ls,rs;}f[N * 30];
bool cmp(nd x,nd y){return x.z < y.z;}
void build(int &p,int l,int r)
{
	p = ++size,f[p] = tree{r - l + 1,r - l + 1,r - l + 1,0,0};
	if (l == r) return; int mid = l + r >> 1;
	build(f[p].ls,l,mid),build(f[p].rs,mid + 1,r);
}
void update(int &p1,int p2,int l,int r,int u)
{
	p1 = ++size,f[p1].ls = f[p2].ls,f[p1].rs = f[p2].rs;
	if (l == r) return f[p1] = tree{-1,-1,-1,0,0},void();
	int mid = l + r >> 1;
	if (u <= mid) update(f[p1].ls,f[p2].ls,l,mid,u);
	else update(f[p1].rs,f[p2].rs,mid + 1,r,u);
	int ls = f[p1].ls,rs = f[p1].rs;
	f[p1].z = f[ls].z + f[rs].z,f[p1].lz = max(f[ls].lz,f[rs].lz + f[ls].z);
	f[p1].rz = max(f[rs].rz,f[ls].rz + f[rs].z);
}
int query(int p,int l,int r,int L,int R)
{
	if (L <= l && r <= R) return f[p].z;
	int mid = l + r >> 1,tmp = 0;
	if (L <= mid) tmp = query(f[p].ls,l,mid,L,R);
	if (R > mid) tmp += query(f[p].rs,mid + 1,r,L,R);
	return tmp;
}
int queryl(int p,int l,int r,int L,int R)
{
	if (L <= l && r <= R) return f[p].lz;
	int mid = l + r >> 1;
	if (R <= mid) return queryl(f[p].ls,l,mid,L,R);
	if (L > mid) return queryl(f[p].rs,mid + 1,r,L,R);
	return max(queryl(f[p].ls,l,mid,L,R),query(f[p].ls,l,mid,L,R) + queryl(f[p].rs,mid + 1,r,L,R)); 
}
int queryr(int p,int l,int r,int L,int R)
{
	if (L <= l && r <= R) return f[p].rz;
	int mid = l + r >> 1;
	if (R <= mid) return queryr(f[p].ls,l,mid,L,R);
	if (L > mid) return queryr(f[p].rs,mid + 1,r,L,R);
	return max(queryr(f[p].rs,mid + 1,r,L,R),queryr(f[p].ls,l,mid,L,R) + query(f[p].rs,mid + 1,r,L,R)); 
}
int main()
{
	scanf("%d",&n);
	for (int i = 1; i <= n; i++) scanf("%lld",&a[i].z),a[i].id = i;
	sort(a + 1,a + 1 + n,cmp),build(rt[1],1,n);
	for (int i = 1; i < n; i++) update(rt[i + 1],rt[i],1,n,a[i].id);
	scanf("%d",&m);
	for (int i = 1; i <= m; i++)
	{
		scanf("%lld%lld%lld%lld",&q[0],&q[1],&q[2],&q[3]);
		for (int j = 0; j < 4; j++) q[j] = (q[j] + ans) % n + 1LL;
		sort(q,q + 4); int l = 1,r = n;
		while (l <= r)
		{
			int mid = l + r >> 1,x1 = query(rt[mid],1,n,q[1] + 1,q[2] - 1);
			int x2 = queryr(rt[mid],1,n,q[0],q[1]),x3 = queryl(rt[mid],1,n,q[2],q[3]);
			if (x1 + x2 + x3 >= 0) ans = mid,l = mid + 1; else r = mid - 1;
		}
		ans = a[ans].z,printf("%lld\n",ans);
	}
 }