BZOJ-3524 [POI2014]Couriers
树状数组套权值线段树,然后对于每个询问进行二分答案。
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define clr(x, c) memset(x, c, sizeof(x))
#define lowbit(x) (x&-x)
#define maxn 500009
#define maxm 10000009
#define inf 0x7fffffff
#define s(x) Sum[x]
#define t(x) Tree[x]
#define l(x) Left[x]
#define r(x) Right[x]
using namespace std;
inline int read()
{
int x=0, f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();
return x*f;
}
int n, m, z, Tree[maxn], Left[maxm], Right[maxm], Sum[maxm];
void Add(int k, int l, int r, int u, int &t)
{
if (!t) t=++z;
s(t)=s(u)+1;
if (l==r) return; int mid=(l+r)>>1;
if (k<=mid) r(t)=r(u), Add(k, l, mid, l(u), l(t));
else l(t)=l(u), Add(k, mid+1, r, r(u), r(t));
}
inline int Query(int l, int r)
{
int tmp=(r-l+1)/2, L=1, R=n, x=t(l-1), y=t(r);
while (L<R)
{
if (s(y)-s(x)<=tmp) return 0;
int mid=(L+R)>>1;
if (s(l(y))-s(l(x))>tmp) R=mid, x=l(x), y=l(y);
else if (s(r(y))-s(r(x))>tmp) L=mid+1, x=r(x), y=r(y);
else return 0;
}
return L;
}
int main()
{
n=read(), m=read(); t(0)=++z, l(z)=r(z)=z;
rep(i, 1, n) Add(read(), 1, n, t(i-1), t(i));
rep(i, 1, m)
{
int l=read(), r=read();
printf("%d\n", Query(l, r));
}
return 0;
}

浙公网安备 33010602011771号