bzoj4170 极光

Posted llppdd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
", ans[i]);
    }
}

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

以上是关于bzoj4170 极光的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2989&&4170数列——二进制分组+主席树

解题报告:luogu P4170

解题报告:luogu P4170

P4170 [CQOI2007]涂色(区间dp)

极光推送实战感受

Bzoj2339--Hnoi2011卡农