传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6621
队友一上来分块RE了一发,搞得我也想分块,结果lts一声主席树,然后就发现是主席树板题了。。。
直接权值主席树,下标表示值,记录的sum表示当前值的个数就行了,然后二分答案,得到上下界,用rt[r]-rt[l-1]去找就行了。
#include
#define maxl 100010
using namespace std;
const int nn=1e6;
int n,m,tot,ans;
int rt[maxl],a[maxl];
struct node
{
int ls,rs,sum;
}tree[maxl*10*35];
inline void insert(int num,int &x,int l,int r)
{
tree[++tot]=tree[x];x=tot;
++tree[x].sum;
if(l==r) return;
int mid=(l+r)>>1;
if(num<=mid)
insert(num,tree[x].ls,l,mid);
else
insert(num,tree[x].rs,mid+1,r);
}
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
tree[0].ls=tree[0].rs=tree[0].sum=0;
rt[0]=0;
tot=0;
for(int i=1;i<=n;i++)
{
rt[i]=rt[i-1];
insert(a[i],rt[i],1,nn);
}
}
inline int query(int i,int j,int l,int r,int i1,int j1)
{
if(i1==l && j1==r)
return tree[j].sum-tree[i].sum;
int mid=(i1+j1)>>1,ret;
if(r<=mid)
ret=query(tree[i].ls,tree[j].ls,l,r,i1,mid);
else if(l>mid)
ret=query(tree[i].rs,tree[j].rs,l,r,mid+1,j1);
else
{
ret=query(tree[i].ls,tree[j].ls,l,mid,i1,mid);
ret+=query(tree[i].rs,tree[j].rs,mid+1,r,mid+1,j1);
}
return ret;
}
inline bool jug(int l,int r,int mid,int p,int k)
{
int up=min(p+mid,nn),lo=max(1,p-mid);
int sum=query(rt[l-1],rt[r],lo,up,1,nn);
if(sum>1;
if(!jug(lo,up,mid,p,k))//