您的位置:首页 > 产品设计 > UI/UE

[置顶] HDU 5919 Sequence II(主席树)

2016-10-07 10:06 295 查看
题意:给出一个长度为n的序列,m次询问,每次询问取出【l,r】区间内所有第一次出现的数字下标,输出这些下标的中位数,强制在线

分析:由于需要强制在线处理,并且没有修改,所以考虑用主席树,统计第一次出现的数字下标,直接倒着扫一遍数组建树,每一次询问,统计区间个数,二分查找第k个数,复杂度mlog(n)

#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 200004

struct node
{
int l,r;
int sum;
node()
{
sum=l=r=0;
}
} t[maxn*40];

int n,m;
int cnt;
int a[maxn],root[maxn];
int vis[maxn];

void update(int d,int &now,int pre,int pos,int l,int r)
{
t[now=++cnt]=t[pre],t[now].sum+=d;
if(l==r) return ;
int mid=l+r>>1;
if(pos<=mid) update(d,t[now].l,t[pre].l,pos,l,mid);
else update(d,t[now].r,t[pre].r,pos,mid+1,r);
}

int query1(int now,int pos,int l,int r)
{
if(t[now].sum==0) return 0;
if(l==pos&&r==pos)
{
return t[now].sum;
}
int mid=l+r>>1;
if(pos<=mid) return query1(t[now].l,pos,l,mid);
else return t[t[now].l].sum+query1(t[now].r,pos,mid+1,r);
}

int query2(int num,int now,int l,int r)
{
if(l==r)
{
return l;
}
int mid=l+r>>1;
int temp=t[t[now].l].sum;
if(temp<num) return query2(num-temp,t[now].r,mid+1,r);
else return query2(num,t[now].l,l,mid);
}

int main()
{
int ca=1;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
cnt=0;
root[n+1]=0;
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=n; i>=1; i--)
{
update(1,root[i],root[i+1],i,1,n);
if(vis[a[i]])
{
if(vis[a[i]]>=1&&vis[a[i]]<=n)
update(-1,root[i],root[i],vis[a[i]],1,n);
}
vis[a[i]]=i;
}
printf("Case #%d:",ca++);
int ans=0;
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
int x,y;
x=min(((l+ans)%n)+1,((r+ans)%n)+1);
y=max(((l+ans)%n)+1,((r+ans)%n)+1);
l=x;
r=y;
int num=query1(root[l],r,1,n)+1;
num/=2;
ans=query2(num,root[l],1,n);
printf(" %d",ans);
}
puts("");
for(int i=1; i<=n; i++) vis[a[i]]=0;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: