BZOJ 2989: 數列 二維線段樹

2989: 數列

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 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

Sample Output

2
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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章