POJ 1195 Mobile phones(二维线段树)

题目链接
题意:
给予\(n * n\)的矩阵,两种操作:

  1. \(x\) \(y\) \(d\),点\((x,y)\)的值增加d。
  2. \(x_1\) \(y_1\) \(x_2\) \(y_2\),查询矩阵\(x_1<=x<=x_2\),\(y_1<=y<=y_2\)内的元素和。

思路:
二维线段树,即线段树的每个节点内又有一个线段树,建树复杂度\(O(n^2)\),查询复杂度\(O(({logn})^2)\)。两种操作对应二维线段树单点更新,区间查询。

code:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <deque>
#include <cmath>
#include <ctime>
#include <map>
#include <set>

#define fi first
#define se second
#define pb push_back
#define endl "\n"
#define debug(x) cout << #x << ":" << x << endl;
#define bug cout << "********" << endl;
#define all(x) x.begin(), x.end()
#define lowbit(x) x & -x
#define fin(x) freopen(x, "r", stdin)
#define fout(x) freopen(x, "w", stdout)
#define ull unsigned long long
#define ll long long 

const double eps = 1e-15;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const int mod =  1e9 + 7;
const int maxn = 1e3 + 10;

using namespace std;

#define lson rt << 1 
#define rson rt << 1 | 1

ll t[maxn << 2][maxn << 2];
int n;

void rebuild(int rt, int l, int r, int num){
    t[num][rt] = 0;
    if(l == r)return ;
    int mid = l + r >> 1;
    rebuild(lson, l, mid, num), rebuild(rson, mid + 1, r, num);
}

void build(int rt, int l, int r){
    rebuild(1, 1, n, rt);
    if(l == r)return;
    int mid = l + r >> 1;
    build(lson, l, mid), build(rson, mid + 1, r);
}

void reupdate(int rt, int l, int r, int y, int num, int d){
    if(l == r)return void(t[num][rt] += d);
    int mid = l + r >> 1;
    if(y <= mid)reupdate(lson, l, mid, y, num, d);
    else reupdate(rson, mid + 1, r, y, num, d);
    t[num][rt] = t[num][lson] + t[num][rson];
}

void update(int rt, int l, int r, int x, int y, int d){
    reupdate(1, 1, n, y, rt, d);
    if(l == r)return;
    int mid = l + r >> 1;
    if(x <= mid)update(lson, l, mid, x, y, d);
    else update(rson, mid + 1, r, x, y, d);
}

ll requery(int rt, int l, int r, int Y1, int Y2, int num){
    if(Y1 <= l && r <= Y2)return t[num][rt];
    int mid = l + r >> 1;
    ll ret = 0;
    if(Y1 <= mid)ret += requery(lson, l, mid, Y1, Y2, num);
    if(mid < Y2)ret += requery(rson, mid + 1, r, Y1, Y2, num);
    return ret;
}

ll query(int rt, int l, int r, int X1, int Y1, int X2, int Y2){
    if(X1 <= l && r <= X2)return requery(1, 1, n, Y1, Y2, rt);
    int mid = l + r >> 1;
    ll ret = 0;
    if(X1 <= mid)ret += query(lson, l, mid, X1, Y1, X2, Y2);
    if(mid < X2)ret += query(rson, mid + 1, r, X1, Y1, X2, Y2);
    return ret;
}

int main(){
    int a1, b1, a2, b2, t, y;
    while(~scanf("%d", &t)){
        if(t == 0)scanf("%d", &n), build(1, 1, n);
        else if(t == 1){
            scanf("%d%d%d", &a1, &b1, &y);
            a1 ++, b1 ++;
            update(1, 1, n, a1, b1, y);
        }
        else if(t == 2){
            scanf("%d%d%d%d", &a1, &b1, &a2, &b2);
            a1 ++, b1 ++, a2 ++, b2 ++;
            ll ans = query(1, 1, n, a1, b1, a2, b2);
            printf("%lld\n", ans);
        }
        else break;
    }
    return 0;
}
上一篇:sms发送短信验证码


下一篇:python学习笔记-方法