您的位置:首页 > 其它

zoj 3633 线段树单点更新 区间最大值

2012-09-05 17:41 471 查看
/*
解法是,先把所有数字从小到大排序,相同的按出现的先后顺序排序。
更新时,对于每一个数x,如果前面的y==x的话,那么在线段树中,在x的坐标位置上赋值上y的坐标位置。
查询时,[a,b]就是查询区间[a,b]中大于等于a的最大值。如果最大值都小于a,那么就说明没有重复的。

比如上面的数据1 2 3 1 2,排序后就是:
1  1  2  2  3
pos:1  4  2  5  3
再次排序后:
pos: 1 2 3 4 5
key: 0 0 0 1 2
那么 显然【1,4】的答案为 X[1],[1,5]的答案为X[2];
[x,y]中key 的最大值<x,那么为OK,否则就为 X[maxkey];
*/
#include<iostream>
#include<algorithm>
#include<memory.h>
#include<cstdio>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
const int maxn=500002;
const int maxm=50002;
struct node
{
int pos,data,key;
}p[maxn<<2];
int pos[maxn],n,m,ans,Max[maxn<<2],X[maxn];
void PushUP(int rt)
{
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
Max[rt]=pos[l];
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
PushUP(rt);
}
void update(int rt,int l,int r,int idx,int data)
{
if(l==r)
{
Max[rt]=data;
return;
}
int mid=(l+r)>>1;
if(mid>=idx) update(lson,idx,data);
else update(rson,idx,data);
PushUP(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return Max[rt];
}
int mid=(l+r)>>1;
int s1=0,s2=0;
if(mid>=L) s1=query(lson,L,R);
if(R>mid)  s2=query(rson,L,R);
return max(s1,s2);
}
int cmp1(node a,node b)
{
if(a.data!=b.data)return a.data<b.data;
return a.pos<b.pos;
}
int cmp2(node a,node b)
{
return a.pos<b.pos;
}
int main()
{
int a,b;
while(scanf("%d",&n)==1)
{
memset(Max,0,sizeof(Max));
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i].data);
p[i].pos=i;
p[i].key=0;
X[i]=p[i].data;
}
sort(p+1,p+n+1,cmp1);
for(int i=2;i<=n;i++)
{
if(p[i].data==p[i-1].data)
{
p[i].key=p[i-1].pos;
}
}
sort(p+1,p+n+1,cmp2);
for(int i=1;i<=n;i++)
{
pos[i]=p[i].key;
}
build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{

scanf("%d%d",&a,&b);
ans=query(1,1,n,a,b);
if(ans>=a)
{
printf("%d\n",X[ans]);
}
else printf("OK\n");
}
cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: