2989: 數列
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 466 Solved: 211
[Submit][Status][Discuss]
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
2 4 3
Query 2 2
Modify 1 3
Query 2 2
Modify 1 2
Query 1 1
Sample Output
2
3
3
3
3
HINT
N<=60000 修改操作數<=40000 詢問<=50000 Max{a[i]}含修改<=100000
這個題挺顯然的
可持久化就是逗你玩兒 實際就是加點
KDT求矩形點數是很明顯的做法
爲了鍛鍊數據結構能力寫了二維線段樹
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=100100,M=20001000;
const int lim[2]={-100000,100000},maxn=160000;
struct seg_tree{int ls,rs,w;}tr[M];
int root[maxn<<2],sz;
void in_modify(int &k,int l,int r,int y)
{
if(!k) k=++sz;tr[k].w++;
if(l==r) return ;
int mid=(l+r)>>1;
y<=mid ? in_modify(tr[k].ls,l,mid,y) : in_modify(tr[k].rs,mid+1,r,y);
}
void out_modify(int k,int l,int r,int x,int y)
{
in_modify(root[k],lim[0],lim[1],y);
if(l==r) return ;int mid=(l+r)>>1;
x<=mid ? out_modify(k<<1,l,mid,x,y) : out_modify(k<<1|1,mid+1,r,x,y);
}
int in_query(int k,int l,int r,int x,int y)
{
if(!k) return 0;
if(l>=x && r<=y) return tr[k].w;
int mid=(l+r)>>1,s(0),t(0);
if(x<=mid) s=in_query(tr[k].ls,l,mid,x,y);
if(y>mid) t=in_query(tr[k].rs,mid+1,r,x,y);
return s+t;
}
int out_query(int k,int l,int r,int x,int y,int X,int Y)
{
if(l>=x && r<=y)
{return in_query(root[k],lim[0],lim[1],X,Y);}
int mid=(l+r)>>1,s(0),t(0);
if(x<=mid) s=out_query(k<<1,l,mid,x,y,X,Y);
if(y>mid) t=out_query(k<<1|1,mid+1,r,x,y,X,Y);
return s+t;
}
int a[N];
int main()
{
int n=read(),Q=read();
register int i,x,K;
for(i=1;i<=n;++i)
a[i]=read(),out_modify(1,1,maxn,a[i]+i,a[i]-i);
char opt[10];
while(Q--)
{
scanf("%s",opt);
x=read();K=read();
switch(opt[0])
{
case 'Q':
print(out_query(1,1,maxn,a[x]+x-K,a[x]+x+K,a[x]-x-K,a[x]-x+K));
puts("");
break;
case 'M':
a[x]=K;
out_modify(1,1,maxn,K+x,K-x);
break;
}
}
return 0;
}