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

HDU 5412 CRB and Queries (Kth number 整体二分 动态转静态)

2016-07-04 10:34 363 查看
题意:

给出长度为n的数列,m次操作

操作分为 1 x y 将x位置的数改成y

2 x y k 查询【x , y】区间内的第k小数

分析:

有了POJ 2104 那题的静态整体二分的基础后就非常好做了

还是离线处理的方法,将所有数据读入然后再整体二分

对于修改操作,将它分为删除操作和添加操作,仔细想想,这样做并不影响整体二分的结果,因为一次修改操作只对后面的有影响,而后面的影响会随着二分消除掉。

要注意一点,由于修改操作改为了两种操作,所以总空间应该开到 n+2*m

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 320000

struct node
{
int val,l,r,k;
int index,kind;
} q[maxn],q1[maxn],q2[maxn];

int n,m;
int a[maxn];
int c[maxn];
int ans[maxn];

inline int lowbit(int x)
{
return x&-x;
}

inline void update(int x,int val)
{
for(; x<=n; x+=lowbit(x)) c[x]+=val;
}

inline int query(int x)
{
int sum=0;
for(; x>0; x-=lowbit(x)) sum+=c[x];
return sum;
}

void divide(int s,int t,int l,int r)
{
if(s>t) return ;
if(l==r)
{
for(int i=s; i<=t; i++)
{
if(q[i].kind==2)
{
ans[q[i].index]=l;
}
}
return ;
}
int mid=(l+r)>>1;
int num1=0,num2=0;
int flag1=0,flag2=0;
for(int i=s; i<=t; i++)
{
if(q[i].kind==2)
{
int tmp=query(q[i].r)-query(q[i].l-1);
if(tmp>=q[i].k) q1[num1++]=q[i],flag1=1;
else q[i].k-=tmp,q2[num2++]=q[i],flag2=1;
}
else
{
if(q[i].val<=mid) update(q[i].index,q[i].kind),q1[num1++]=q[i];
else q2[num2++]=q[i];
}
}
for(int i=s; i<=t; i++)
{
if(q[i].kind!=2)
{
if(q[i].val<=mid) update(q[i].index,-q[i].kind);
}
}
for(int i=0; i<num1; i++) q[s+i]=q1[i];
for(int i=0; i<num2; i++) q[s+num1+i]=q2[i];
if(flag1) divide(s,s+num1-1,l,mid);
if(flag2) divide(s+num1,t,mid+1,r);
}

int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof c);
int cnt=1;
int mm=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
q[cnt].val=a[i];
q[cnt].index=i;
q[cnt].kind=1;
cnt++;
}
scanf("%d",&m);
int num=0;
for(int i=1; i<=m; i++)
{
int op;
scanf("%d",&op);
if(op==2)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
q[cnt].l=l;
q[cnt].r=r;
q[cnt].k=k;
q[cnt].kind=2;
q[cnt].index=num++;
cnt++;
}
else
{
int x,val;
scanf("%d%d",&x,&val);
q[cnt].val=a[x];
q[cnt].index=x;
q[cnt].kind=-1;
cnt++;
q[cnt].index=x;
q[cnt].val=val;
q[cnt].kind=1;
cnt++;
a[x]=val;
}
}
divide(1,cnt-1,1,INF);
for(int i=0; i<num; i++)
{
printf("%d\n",ans[i]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: