【BZOJ】3542: DZY Loves March

题意

\(m * m\)的网格,有\(n\)个点。\(t\)个询问:操作一:第\(x\)个点向四个方向移动了\(d\)个单位。操作二:询问同行同列其他点到这个点的曼哈顿距离和。强制在线。(\(n \le 10^5,m \le 10^{18}\)

分析

没啥好分析的,就是推一下能推出每行每列的一个式子来,然后套两个区间维护的结构就行了。

题解

set + 线段树

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mo=1e9+7, N=100005;
int n;
ll x[N], y[N];
template<class T>
inline void fix(T &x) {
    if(x>=mo || x<=-mo) x%=mo;
    if(x<0) x+=mo;
}
struct dat {
    int s, sum1, sum2;
    void init() {
        s=sum1=sum2=0;
    }
    void add(int _s, int go) {
        s+=_s;
        sum1+=(ll)go*go%mo*_s; fix(sum1);
        sum2+=go*_s; fix(sum2);
    }
};
dat operator + (const dat &a, const dat &b) {
    static dat x;
    x.s=a.s+b.s;
    x.sum1=a.sum1+b.sum1; fix(x.sum1);
    x.sum2=a.sum2+b.sum2; fix(x.sum2);
    return x;
}
struct node *null;
struct node {
    node *c[2];
    dat d;
    void up() {
        d=c[0]->d+c[1]->d;
    }
    void init() {
        d.init();
        c[0]=c[1]=null;
    }
}Po[5000005], *iT=Po, *bin[5000005], **iTbin=bin;
node *newnode() {
    node *x;
    if(iTbin!=bin) x=*(--iTbin);
    else {
        if(iT==Po+5000000) x=new node;
        else x=iT++;
    }
    x->init();
    return x;
}
void delnode(node *&x) {
    *iTbin=x;
    iTbin++;
    x=null;
}
void seginit() {
    null=newnode();
    null->init();
}
void update(int p, int s, int go, int l, int r, node *&x) {
    if(x==null) {
        x=newnode();
    }
    if(l==r) {
        x->d.add(s, go);
        if(x->d.s==0) {
            delnode(x);
        }
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) {
        update(p, s, go, l, mid, x->c[0]);
    }
    else {
        update(p, s, go, mid+1, r, x->c[1]);
    }
    x->up();
    if(x->d.s==0) {
        delnode(x);
    }
}
dat ask(int L, int R, int l, int r, node *x) {
    static dat nul={0, 0, 0};
    if(x==null) {
        return nul;
    }
    if(L<=l && r<=R) {
        return x->d;
    }
    int mid=(l+r)>>1;
    dat ret;
    ret.init();
    if(L<=mid) {
        ret=ask(L, R, l, mid, x->c[0]);
    }
    if(mid<R) {
        ret=ret+ask(L, R, mid+1, r, x->c[1]);
    }
    return ret;
}
map<ll, node *> X, Y;
void add(ll x, int s, int go, int id, map<ll, node *> &a) {
    if(a.find(x)==a.end()) {
        a[x]=null;
    }
    node *&it=a[x];
    update(id, s, go, 1, n, it);
    if(it==null) a.erase(a.find(x));
}
dat ask(ll x, int L, int R, map<ll, node *> &a) {
    return ask(L, R, 1, n, a[x]);
}
int main() {
    seginit();
    int m;
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; ++i) {
        ll _x, _y;
        scanf("%lld%lld", &_x, &_y);
        x[i]=_x;
        y[i]=_y;
        fix(_x);
        fix(_y);
        add(x[i], 1, _y, i, X);
        add(y[i], 1, _x, i, Y);
    }
    int T, ans=0;
    scanf("%d", &T);
    while(T--) {
        char s[5];
        int pos;
        scanf("%s%d", s, &pos);
        pos^=ans;
        if(s[0]=='Q') {
            int L, R;
            scanf("%d%d", &L, &R);
            dat d1, d2;
            d2=ask(x[pos], L, R, X);
            d1=ask(y[pos], L, R, Y);
            ans=0;
            ll ans1=0, ans2=0, tx=x[pos], ty=y[pos];
            fix(tx);
            fix(ty);
            ans1=-((tx*d1.sum2%mo)<<1)+tx*tx%mo*d1.s+d1.sum1;
            ans2=-((ty*d2.sum2%mo)<<1)+ty*ty%mo*d2.s+d2.sum1;
            fix(ans1);
            fix(ans2);
            ans=ans1+ans2;
            fix(ans);
            printf("%d\n", ans);
        }
        else {
            ll d;
            scanf("%lld", &d);
            ll _x=x[pos], _y=y[pos];
            if(s[0]=='U') y[pos]+=d;
            if(s[0]=='D') y[pos]-=d;
            if(s[0]=='R') x[pos]+=d;
            if(s[0]=='L') x[pos]-=d;
            add(_x, -1, _y%mo, pos, X);
            add(_y, -1, _x%mo, pos, Y);
            add(x[pos], 1, y[pos]%mo, pos, X);
            add(y[pos], 1, x[pos]%mo, pos, Y);
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/iwtwiioi/p/4986028.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值