您的位置:首页 > 其它

[BZOJ]4170: 极光 2989: 数列 CDQ分治+树状数组

2017-11-30 15:58 344 查看
Description

给定一个长度为n的正整数数列a[i]。

定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|。

2种操作(k都是正整数):

1.Modify x k:将第x个数的值修改为k。

2.Query x k:询问有几个i满足graze(x,i)<=k。因为可持久化数据结构的流行,询问不仅要考虑当前数列,还要考虑任意历史版本,即统计任意位置上出现过的任意数值与当前的a[x]的graze值<=k的对数。(某位置多次修改为同样的数值,按多次统计)

题解:

一开始看,分四种情况讨论的话是四维偏序,后来灵机一动,把它看做平面上的点的话,求的就是距离不超过k的有多少个点,这个区域恰好是一个菱形,那么把坐标系旋转一下,就可以变成询问一个矩形内数的和了,那么就和简单题的方法一样了。(不知道为什么数组要莫名开大)

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxq=150010;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,Q,a[600100],cnt,idcnt=0;
int X(int x,int y){return x+y-1;}
int Y(int x,int y){return n-x+y;}
LL ans[500100];
struct Opt{int x,y,k,type,id;}q[Maxq],q1[Maxq<<2],temp[Maxq<<2];
int s[4000010];
void add(int x,int y){if(x<=0)return;for(;x<=4000000;x+=(x&-x))s[x]+=y;}
LL getsum(int x){LL re=0;for(;x>0;x-=(x&-x))re+=(LL)(s[x]);return re;}
int List[Maxq<<2];
void solve(int l,int r)
{
if(l==r)return;
int mid=l+r>>1;
solve(l,mid);solve(mid+1,r);
int i=l,j=mid+1,len=0,o=0;
while(i<=mid&&j<=r)
{

10b4f
if(q1[i].x<q1[j].x||(q1[i].x==q1[j].x&&q1[i].type<q1[j].type))
{
if(q1[i].type==1)add(q1[i].y,1),List[++o]=q1[i].y;
temp[++len]=q1[i++];
}
else
{
if(q1[j].type==2)ans[q1[j].id]+=getsum(q1[j].y);
else if(q1[j].type==3)ans[q1[j].id]-=getsum(q1[j].y);
temp[++len]=q1[j++];
}
}
int t=i;
while(i<=mid)temp[++len]=q1[i++];
while(j<=r)
{
if(q1[j].type==2)ans[q1[j].id]+=getsum(q1[j].y);
else if(q1[j].type==3)ans[q1[j].id]-=getsum(q1[j].y);
temp[++len]=q1[j++];
}
for(int p=1;p<=o;p++)add(List[p],-1);
for(int p=1;p<=len;p++)q1[l+p-1]=temp[p];
}
int main()
{
n=read(),Q=read();
for(int i=1;i<=n;i++)q[i].type=1,q[i].x=i,q[i].y=a[i]=read();
for(int i=1;i<=Q;i++)
{
char op[8];
scanf("%s",op);
int u1=read(),u2=read(),t=i+n;
if(op[0]=='M')q[t].type=1,q[t].x=u1,q[t].y=u2,a[u1]=u2;
else q[t].type=2,q[t].x=u1,q[t].y=a[u1],q[t].k=u2,q[t].id=++idcnt;
}
for(int i=1;i<=n;i++)q1[i]=q[i],q1[i].x=X(q[i].x,q[i].y),q1[i].y=Y(q[i].x,q[i].y);cnt=n;
for(int i=1+n;i<=Q+n;i++)
{
if(q[i].type==1)q1[++cnt]=q[i],q1[cnt].x=X(q[i].x,q[i].y),q1[cnt].y=Y(q[i].x,q[i].y);
else
{
int X1=q[i].x,Y1=q[i].y-q[i].k,X2=q[i].x,Y2=q[i].y+q[i].k;
int x1=X(X1,Y1),y1=Y(X1,Y1),x2=X(X2,Y2),y2=Y(X2,Y2);
q1[++cnt].type=2;q1[cnt].x=x2;q1[cnt].y=y2;
q1[++cnt].type=2;q1[cnt].x=x1-1;q1[cnt].y=y1-1;
q1[++cnt].type=3;q1[cnt].x=x1-1;q1[cnt].y=y2;
q1[++cnt].type=3;q1[cnt].x=x2;q1[cnt].y=y1-1;
q1[cnt].id=q1[cnt-1].id=q1[cnt-2].id=q1[cnt-3].id=q[i].id;
}
}
solve(1,cnt);
for(int i=1;i<=idcnt;i++)printf("%lld\n",ans[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: