1. 程式人生 > >BZOJ4822[Cqoi2017]老C的任務——樹狀數組(二維數點)

BZOJ4822[Cqoi2017]老C的任務——樹狀數組(二維數點)

cpp 管理系 一個 經典 維數 ask bzoj algorithm else

題目描述

老 C 是個程序員。 最近老 C 從老板那裏接到了一個任務——給城市中的手機基站寫個管理系統。作為經驗豐富的程序員,老 C 輕松 地完成了系統的大部分功能,並把其中一個功能交給你來實現。由於一個基站的面積相對於整個城市面積來說非常 的小,因此每個的基站都可以看作坐標系中的一個點,其位置可以用坐標(x, y)來表示。此外,每個基站還有很多屬 性,例如高度、功率等。運營商經常會劃定一個區域,並查詢區域中所有基站的信息。現在你需要實現的功能就是, 對於一個給定的矩形區域,回答該區域中(包括區域邊界上的)所有基站的功率總和。如果區域中沒有任何基站,則回 答 0。

輸入

第一行兩個整數 n, m,表示一共有n個基站和m次查詢。 接下來一共有 n 行,每行由x_i , y_i , p_i 三個空格隔開的整數構成,表示一個基站的坐標(x_i , y_i )和功率p _i 。不會有兩個基站位於同一坐標。 接下來一共有m行,每行由x1_j , y1_j , x2_j , y2_j 四個空格隔開的整數構成,表示一次查詢的矩形區域。該矩 形對角坐標為(x1_j , y1_j )和(x2_j , y2_j ),且 4 邊與坐標軸平行。 2^31 ≤ x_i , y_i , p_i , x1_j , y1_j , x2_j , y2_j < 2^31, x1_j ≤ x2_j, y1_j ≤ y2_j。

輸出

輸出 m 行,每行一個整數,對應每次查詢的結果。

樣例輸入

4 2
0 0 1
0 1 2
2 2 4
1 0 8
0 0 1 1
1 1 5 6

樣例輸出

11
4
  經典的二維數點問題,離線詢問,將給出的點和詢問的點一起排序,按排序後順序操作,詢問就直接樹狀數組上查詢,插入點在樹狀數組對應位置加上就好了。但註意要離散化並且開longlong。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct node
{
    int x;
    int y;
    int num;
    int cnt;
    int v;
}s[10000010];
int n,m;
ll v[10000010];
int a,b,c,d;
int g[10000010];
int maxy;
int tot;
ll ans[2000010][5];
void add(int x,int k)
{
    for(int i=x;i<=maxy;i+=i&-i)
    {
        v[i]+=1ll*k;
    }
}
ll ask(int x)
{
    ll res=0;
    for(int i=x;i;i-=i&-i)
    {
        res+=v[i];
    }
    return res;
}
bool cmp(node a,node b)
{
    if(a.x==b.x)
    {
        if(a.y==b.y)
        {
            return a.cnt<b.cnt; 
        }
        return a.y<b.y;
    }
    return a.x<b.x;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)   
    {
        scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].v);
        g[i]=s[i].y;
    }
    tot=n;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&a,&b,&c,&d);
        s[++tot].x=a-1;
        s[tot].y=b-1;
        s[tot].cnt=i;
        s[tot].num=1;
        g[tot]=b-1;
        s[++tot].x=a-1;
        s[tot].y=d;
        s[tot].cnt=i;
        s[tot].num=2;
        g[tot]=d;
        s[++tot].x=c;
        s[tot].y=b-1;
        s[tot].cnt=i;
        s[tot].num=3;
        g[tot]=b-1;
        s[++tot].x=c;
        s[tot].y=d;
        s[tot].cnt=i;
        s[tot].num=4;
        g[tot]=d;
    }
    sort(g+1,g+1+tot);
    sort(s+1,s+1+tot,cmp);
    maxy=unique(g+1,g+1+tot)-g-1;
    for(int i=1;i<=tot;i++)
    {
        if(!s[i].cnt)
        {
            int val=lower_bound(g+1,g+1+maxy,s[i].y)-g;
            add(val,s[i].v);
        }
        else
        {
            int val=lower_bound(g+1,g+1+maxy,s[i].y)-g;
            ans[s[i].cnt][s[i].num]=ask(val);
        }
    }
    for(int i=1;i<=m;i++)
    {
        printf("%lld\n",ans[i][4]+ans[i][1]-ans[i][2]-ans[i][3]);
    }
}

BZOJ4822[Cqoi2017]老C的任務——樹狀數組(二維數點)