bzoj4170 极光

极光

Time Limit: 30 Sec Memory Limit: 512 MB

Description

"若是万一琪露诺(俗称rhl)进行攻击,什么都好,冷静地回答她的问题来吸引她。对方表现出兴趣的话,那就慢
慢地反问。在她考虑答案的时候,趁机逃吧。就算是很简单的问题,她一定也答不上来。"
--《上古之魔书》
天空中出现了许多的北极光,这些北极光组成了一个长度为n的正整数数列a[i],远古之魔书上记载到:2个位置的g
raze值为两者位置差与数值差的和:
graze(x,y)=|x-y|+|a[x]-a[y]|。
要想破解天罚,就必须支持2种操作(k都是正整数):
Modify x k:将第x个数的值修改为k。
Query x k:询问有几个i满足graze(x,i)<=k。
由于从前的天罚被圣王lmc破解了,所以rhl改进了她的法术,询问不仅要考虑当前数列,还要考虑任意历史版本,
即统计任意位置上出现过的任意数值与当前的a[x]的graze值<=k的对数。(某位置多次修改为同样的数值,按多次
统计)

Input

第1行两个整数n,q。分别表示数列长度和操作数。
第2行n个正整数,代表初始数列。
第3~q+2行每行一个操作。
N<=40000, 修改操作数<=60000, 询问操作数<=10000, Max{a[i]}(含修改)<=80000

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




曼哈顿距离是斜着的正方形,切比雪夫距离是正的正方形
变成正的好维护一些。。。
注意变的时候坐标有负数。。。


QAQ


#include<bits/stdc++.h>
#define lowbit(x) ((x) & (-x))
using namespace std;
const int maxn = 1000521, lim = 1000520;
struct lpl{int t, x, y, q, val;}ini[maxn], lin;
int n, q, cnt, tot, tim, ans[maxn], num[maxn], tree[maxn];
char s[129];
stack<lpl> sss;

inline void putit()
{
	scanf("%d%d", &n, &q); lin.t = 0;
	for(int i = 1; i <= n; ++i){
		scanf("%d", &lin.y); lin.x = i; num[i] = lin.y;
		ini[++cnt].x = lin.x + lin.y; ini[cnt].y = lin.x - lin.y; ini[i].t = ++tim;
	}
	for(int k, i = 1; i <= q; ++i){
		scanf("%s", s + 1);
		if(s[1] == 'Q'){
			scanf("%d%d", &lin.x, &k); lin.y = num[lin.x];
			ini[++cnt].q = ++tot; ini[cnt].val = 1; ini[cnt].t = ++tim;
			ini[cnt].x = lin.x + lin.y + k; ini[cnt].y = lin.x - lin.y + k;
			
			ini[++cnt].q = tot;	ini[cnt].val = -1; ini[cnt].t = tim;
			ini[cnt].x = lin.x + lin.y - k - 1; ini[cnt].y = lin.x - lin.y + k;
			
			ini[++cnt].q = tot;	ini[cnt].val = -1; ini[cnt].t = tim;
			ini[cnt].x = lin.x + lin.y + k; ini[cnt].y = lin.x - lin.y - k - 1;
			
			ini[++cnt].q = tot; ini[cnt].val = 1; ini[cnt].t = tim;
			ini[cnt].x = lin.x + lin.y - k - 1; ini[cnt].y = lin.x - lin.y - k - 1;
		}
		else{
			scanf("%d%d", &lin.x, &lin.y);
			ini[++cnt].x = lin.x + lin.y; ini[cnt].y = lin.x - lin.y; ini[cnt].t = ++tim;
			num[lin.x] = lin.y;
		}
	}
	for(int i = 1; i <= cnt; ++i){
		
		ini[i].x += 200008; ini[i].y += 200008;
	}
}

inline bool cmp1(lpl A, lpl B){return A.x == B.x ? (A.y < B.y) : (A.x < B.x);}

inline void add(int t, int val)
{
	while(t < lim){
		tree[t] += val; t += lowbit(t);
	}
}

inline int query(int t)
{
	int ret = 0;
	if(t <= 0) return ret;
	while(t){
		ret += tree[t]; t -= lowbit(t);
	}
	return ret;
}

void solve(int l, int r)
{
	if(l >= r) return;	
	int mid = (l + r) >> 1;
	solve(l, mid); solve(mid + 1, r);
	sort(ini + l, ini + mid + 1, cmp1); sort(ini + mid + 1, ini + r + 1, cmp1);	
	int p1 = l - 1, p2 = mid + 1;
	while(true){
		while(ini[p1 + 1].x <= ini[p2].x && p1 < mid){
			p1++;
			if(ini[p1].q) continue;
			add(ini[p1].y, 1); sss.push(ini[p1]);
		}
		if(p2 <= r){
			if(ini[p2].q)	ans[ini[p2].q] += (ini[p2].val) * query(ini[p2].y);	
			p2++;
		}
		if(p2 > r) break;
	}
	while(!sss.empty()){
		lin = sss.top(); sss.pop();
		add(lin.y, -1);
	}
}

inline void print()
{
	for(int i = 1; i <= tot; ++i){
		printf("%d\n", ans[i]);
	}
}

int main()
{
	putit();
	solve(1, cnt);
	print();
	return 0;
} 


posted @ 2018-07-14 00:04  沛霖  阅读(251)  评论(0编辑  收藏  举报