【bzoj2989】【数列】【cdq分治+树状数组】

来源:互联网 发布:作头部ct的危害知乎 编辑:程序博客网 时间:2024/05/24 07:07

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的对数。(某位置多次修改为
同样的数值,按多次统计)

Input

第1行两个整数n,q。分别表示数列长度和操作数。
第2行n个正整数,代表初始数列。
第3--q+2行每行一个操作。

Output

对于每次询问操作,输出一个非负整数表示答案

Sample Input

3 5
2 4 3
Query 2 2
Modify 1 3
Query 2 2
Modify 1 2
Query 1 1

Sample Output

2
3
3

HINT

N<=60000 修改操作数<=40000 询问<=50000 Max{a[i]}含修改<=100000

题解:

         首先可以发现所谓的可持久化看成加点即可.

         把(x,a[x])看成一个点.然后我们把曼哈顿距离转化成切比雪夫距离.

         问题就变成了每次询问一个矩形中有多少点.

         把一个矩形拆成4个然后cdq分治+树状数组即可.

         注意坐标不一定都在第一象限,拆分矩形的时候判断一下即可.

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdio>#include<algorithm>#define N 100010#define M 200010using namespace std;int n,m,a[N],tot,x,y,k,cnt,mx,t[M<<2],ans[M];char ch[10]; struct use{int x,y,id,k,v,p;}q[M<<2],p[M<<2];int read(){  int x(0);char ch=getchar();  while(ch<'0'||ch>'9') ch=getchar();  while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();  return x;             }void add(int kind,int p,int x,int y){  int xx=x-y,yy=x+y;mx=max(yy,mx);//cout<<xx<<' '<<yy<<endl;  if (kind==0){q[++tot].x=xx;q[tot].y=yy;q[tot].id=tot;q[tot].k=kind;}  else{    int x1=xx-k,y1=yy-k,x2=xx+k,y2=yy+k;mx=max(mx,y2);    if (y1>0){q[++tot].id=tot;q[tot].k=kind;q[tot].x=x1-1;q[tot].y=y1-1;q[tot].v=1;q[tot].p=p;}    q[++tot].id=tot;q[tot].k=kind;q[tot].x=x1-1;q[tot].y=y2;q[tot].v=-1;q[tot].p=p;    if (y1>0){q[++tot].id=tot;q[tot].k=kind;q[tot].x=x2;q[tot].y=y1-1;q[tot].v=-1;q[tot].p=p;}    q[++tot].id=tot;q[tot].k=kind;q[tot].x=x2;q[tot].y=y2;q[tot].v=1;q[tot].p=p;  }}bool cmp(use a,use b){  if (a.x==b.x){    if (a.y==b.y) return a.id<b.id;    else return a.y<b.y;  }  return a.x<b.x;}int lowbit(int x){return x&(-x);}void add(int x,int v){for (int i=x;i<=mx;i+=lowbit(i)) t[i]+=v;}int query(int x){  int ans(0);  for (int i=x;i;i-=lowbit(i)) ans+=t[i];  return ans;}void solve(int l,int r){  if (l==r) return;  int mid=(l+r)>>1,l1=l,l2=mid+1;  for (int i=l;i<=r;i++){    if (q[i].id<=mid&&!q[i].k) add(q[i].y,1);    if (q[i].id>mid&&q[i].k) ans[q[i].p]+=query(q[i].y)*q[i].v;  }    for (int i=l;i<=r;i++)    if (q[i].id<=mid&&!q[i].k) add(q[i].y,-1);   for (int i=l;i<=r;i++)    if (q[i].id<=mid) p[l1++]=q[i];    else p[l2++]=q[i];  for (int i=l;i<=r;i++) q[i]=p[i];  solve(l,mid);solve(mid+1,r);}int main(){  n=read();m=read();  for (int i=1;i<=n;i++)    a[i]=read(),add(0,0,i,a[i]);  for (int i=n+1;i<=n+m;i++){    scanf("%s",ch);    if (ch[0]=='M') x=read(),y=read(),add(0,0,x,y),a[x]=y;    else x=read(),k=read(),add(1,++cnt,x,a[x]);  }  sort(q+1,q+tot+1,cmp);mx++;  solve(1,tot);  for (int i=1;i<=cnt;i++) printf("%d\n",ans[i]);  }


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 鼻子伤风不通气怎么办 宝宝伤风流鼻子怎么办 十个月婴儿上火怎么办 一个多月宝宝鼻子有鼻屎怎么办 三个月婴儿感冒发烧怎么办 小孩感冒发烧流鼻涕怎么办 小孩感冒发烧反反复复怎么办 宝宝反复发烧39怎么办 一岁婴儿流鼻涕怎么办 四岁宝宝发烧怎么办 小孩流清鼻涕怎么办? 5宝宝光流清鼻涕怎么办 孩子一直流鼻子怎么办 10岁天天流鼻涕怎么办 喉咙痛又痒咳嗽怎么办 60天宝宝流鼻涕怎么办 宝宝流鼻子严重怎么办 鼻炎鼻涕多鼻塞怎么办 夏天老人感冒流鼻涕怎么办 鼻窦炎流清鼻涕怎么办 鼻子有脓鼻涕怎么办 宝宝有脓鼻涕怎么办 小孩脓鼻涕咳嗽怎么办 哺乳期流黄鼻涕怎么办 宝宝鼻塞流脓涕怎么办 喉咙痛浓痰咳嗽怎么办 哺乳期留清鼻涕怎么办 哺乳期就清鼻涕怎么办 小金毛流脓鼻涕怎么办 鼻炎有浓鼻涕怎么办 宝宝流稠鼻涕怎么办 小孩流粘鼻涕怎么办 小孩流黄鼻涕怎么办 鼻炎有脓鼻涕怎么办 小孩鼻子有鼻涕怎么办 小儿浓鼻涕咳嗽怎么办 宝宝冻着流鼻涕怎么办 打喷嚏流清鼻涕怎么办 鼻子老想打喷嚏怎么办 冻着了流鼻涕怎么办 狗狗鼻塞流鼻涕怎么办