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;
}
心如花木,向阳而生。