【POJ1195】Mobile phones

Mobile phones
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 21905   Accepted: 10188

Descriptionios

Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The squares form an S * S matrix with the rows and columns numbered from 0 to S-1. Each square contains a base station. The number of active mobile phones inside a square can change because a phone is moved from a square to another or a phone is switched on or off. At times, each base station reports the change in the number of active phones to the main base station along with the row and the column of the matrix.

Write a program, which receives these reports and answers queries about the current total number of active mobile phones in any rectangle-shaped area.

Inputc++

The input is read from standard input as integers and the answers to the queries are written to standard output as integers. The input is encoded as follows. Each input comes on a separate line, and consists of one instruction integer and a number of parameter integers according to the following table.

The values will always be in range, so there is no need to check them. In particular, if A is negative, it can be assumed that it will not reduce the square value below zero. The indexing starts at 0, e.g. for a table of size 4 * 4, we have 0 <= X <= 3 and 0 <= Y <= 3.

Table size: 1 * 1 <= S * S <= 1024 * 1024
Cell value V at any time: 0 <= V <= 32767
Update amount: -32768 <= A <= 32767
No of instructions in input: 3 <= U <= 60002
Maximum number of phones in the whole table: M= 2^30

Outputide

Your program should not answer anything to lines with an instruction other than 2. If the instruction is 2, then your program is expected to answer the query by writing the answer as a single line containing a single integer to standard output.

Sample Inputui

0 4
1 1 2 3
2 0 0 2 2 
1 1 1 2
1 1 2 -1
2 1 1 2 3 
3

Sample Outputspa

3
4

Source.net

[Submit]   [Go Back]   [Status]   [Discuss] debug

Home Page   Go Back  To topcode

Solution:orm

線段樹套線段樹,第一次寫……blog

反正我此次寫的與常規線段樹不同,外圍X線段樹表示[l,r]內,內層Y線段樹表示內層和。

更新是從上往下的而不是從下往上的,雖然據某fyj同窗說能夠從下往上維護,可是方法不明。

https://blog.csdn.net/zzkksunboy/article/details/70215755 ←這一篇講的特別好,先安利一下。

從新說說這裏吧,也爲之後的本身打個基礎。

實際上,咱們首先用外圍的線段樹維護[x1,x2],並且在每個線段樹的點上建一個線段樹,這顆線段樹用來維護在[x1,x2]區間內的[y1,y2]的值。

這樣的話,咱們修改就對每個走過的地方修改一下,查詢就慢慢往下走了……

我算是發現了,彷佛線段樹上每一個點並不須要儲存l,r信息(這點存疑,至少我目前遇到的全部題目均可以不儲存)。

二維線段樹我以爲很差理解,就沒學,相比之下樹套樹反而顯得很優美。

/*In Search Of Life*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#define debug(x) cerr<<#x<<"="<<x<<endl
#define INF 0x7f7f7f7f
#define llINF 0x7fffffffffffll
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
inline int init()
{
    int now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
inline long long llinit()
{
    long long now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
#define lson (now<<1)
#define rson (now<<1|1)
#define mid ((l+r)>>1)
int sz,v,n; 
struct NodeX
{
    int rooty;
}treeX[5005];
struct NodeY
{
    int lch,rch;
    int sum;
}treeY[5000005];
void Build_Tree_Y(int &now,int l,int r)
{
    now=++sz;
    if(l==r)return;
    else
    {
        Build_Tree_Y(treeY[now].lch,l,mid);
        Build_Tree_Y(treeY[now].rch,mid+1,r);
        treeY[now].sum=treeY[treeY[now].lch].sum+treeY[treeY[now].rch].sum;
    }
}
void Build_Tree_X(int now,int l,int r)
{
    Build_Tree_Y(treeX[now].rooty,1,n);
    if(l==r)return;
    else
    {
        Build_Tree_X(lson,l,mid);
        Build_Tree_X(rson,mid+1,r);
        return;
    }
}
void Modify_Tree_Y(int now,int l,int r,int y)
{
    treeY[now].sum+=v;
    if(l==r)return;
    else
    {
        if(y<=mid)Modify_Tree_Y(treeY[now].lch,l,mid,y);
        else Modify_Tree_Y(treeY[now].rch,mid+1,r,y);
    }
} 
void Modify_Tree_X(int now,int l,int r,int x,int y)
{
    Modify_Tree_Y(treeX[now].rooty,1,n,y);
    if(l==r)return;
    else
    {
        if(x<=mid)Modify_Tree_X(lson,l,mid,x,y);
        else if(x>mid)Modify_Tree_X(rson,mid+1,r,x,y);
    }
}
int Query_Tree_Y(int now,int l,int r,int y1,int y2)
{
    if(l==y1&&r==y2)
    {
        return treeY[now].sum;
    }
    else 
    {
        if(y2<=mid)return Query_Tree_Y(treeY[now].lch,l,mid,y1,y2);
        else if(y1>mid)return Query_Tree_Y(treeY[now].rch,mid+1,r,y1,y2);
        else return Query_Tree_Y(treeY[now].lch,l,mid,y1,mid)+Query_Tree_Y(treeY[now].rch,mid+1,r,mid+1,y2);
    }
}
int Query_Tree_X(int now,int l,int r,int x1,int x2,int y1,int y2)
{
    if(l==x1&&r==x2)
    {
        return Query_Tree_Y(treeX[now].rooty,1,n,y1,y2);
    }
    else 
    {
        if(x2<=mid)return Query_Tree_X(lson,l,mid,x1,x2,y1,y2);
        else if(x1>mid)return Query_Tree_X(rson,mid+1,r,x1,x2,y1,y2);
        else return Query_Tree_X(lson,l,mid,x1,mid,y1,y2)+Query_Tree_X(rson,mid+1,r,mid+1,x2,y1,y2);
    }
}
int t,a,b,c,d;
int main()
{
    while(t=init(),t!=3)
    {
        if(t==0)n=init(),Build_Tree_X(1,1,n);
        else if(t==1)
        {
            a=init();b=init();v=init();
            a++;b++;
            Modify_Tree_X(1,1,n,a,b);
        }
        else if(t==2)
        {
            a=init();b=init();c=init();d=init();
            a++;b++;c++;d++; 
            printf("%d\n",Query_Tree_X(1,1,n,a,c,b,d));
        }
    }
    return 0;
}
View Code

複雜度分析:

空間複雜度:外層線段樹總共$O(n log{n})$,對於每個外部點內部對應一顆線段樹一樣也是$O(n log{n})$,總複雜度$O(n^2log^2{n})$。

時間複雜度:外層查詢每次$O(log{n})$,內層查詢每次$O(log{n})$,總複雜度$O(nlog^2{n})$。

基本就這樣……