uva11297 - Census 线段树套线段树

原创 2015年07月08日 17:23:47

C. Census

Time Limit: 8 sec

Description

This year, there have been many problems with population calculations, since in some cities, there are many emigrants, or the population growth is very high. Every year the ACM (for Association for Counting Members) conducts a census in each region. The country is divided into N^2 regions, consisting of an N x N grid of regions. Your task is to find the least, and the greatest population in some set of regions. Since in a single year there is no significant change in the populations, the ACM modifies the population counts by some number of inhabitants.

The Input

In the first line you will find N (0 <= N <= 500), in following the N lines you will be given N numbers, which represent, the initial population of city C [i, j]. In the following line is the number Q (Q <= 40000), followed by Q lines with queries: 

There are two possible queries: 

- "x1 y1 x2 y2" which represent the coordinates of the upper left and lower right of where you must calculate the maximum and minimum change in population. 

- "x y v" indicating a change of the population of city C [x, y] by value v.

The Output

For each query, "x1 y1 x2 y2" print in a single line the greatest and least amount of current population. Separated each output by a space. 

Notice: There is only a single test case.

Sample Input Sample Output
5 5
1 2 3 4 5
0 9 2 1 3
0 2 3 4 1
0 1 2 4 5
8 5 3 1 4
4
q 1 1 2 3
c 2 3 10
q 1 1 5 5
q 1 2 2 2 
9 0
10 0
9 2

  两种操作,一种是改变某一个位置的值,另一种是询问一个矩阵内的最大最小值。

  假设有x线段树和y线段树,所有的行组成x树,每行对应一个y树。更新的时候对x进行更新[x1,x2]这个区间,对这个区间x上每个点更新y树的[y1,y2]区间,更新y的叶子结点时,如果y树对应的x是叶子结点,那么直接把maxv和minv都变成v,否则maxv[id][o]=max(maxv[id<<1][o],maxv[id<<1|1][o]);minv[id][o]=min(minv[id<<1][o],minv[id<<1|1][o]);因为x叶子节点对应的y这个位置已经更新过,因此用来更新x非叶子结点也就是包含的是一个区间时x对应的y。y非叶子节点的时候由叶子结点递归上来更新就行了。这个题关键就在于对x非叶子节点的y的更新,不是很好理解。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;

const int MAXN=510;
const int MAXNODE=4*MAXN;
const int INF=0x3f3f3f3f;

int N,M,Q;
int ansMax,ansMin;

struct SegmentTree{
    int maxv[MAXNODE][MAXNODE];
    int minv[MAXNODE][MAXNODE];

    void clear(){
        memset(maxv,-INF,sizeof(maxv));
        memset(minv,INF,sizeof(minv));
    }

    void updateSub(int o,int L,int R,int ql,int qr,int id,int v,int flag){
        if(ql<=L&&qr>=R){
            if(flag){
                maxv[id][o]=v;
                minv[id][o]=v;
            }
            else{
                maxv[id][o]=max(maxv[id<<1][o],maxv[id<<1|1][o]);
                minv[id][o]=min(minv[id<<1][o],minv[id<<1|1][o]);
            }
            return;
        }
        int mid=L+(R-L)/2;
        if(ql<=mid) updateSub(o<<1,L,mid,ql,qr,id,v,flag);
        if(qr>mid) updateSub(o<<1|1,mid+1,R,ql,qr,id,v,flag);
        maxv[id][o]=max(maxv[id][o<<1],maxv[id][o<<1|1]);
        minv[id][o]=min(minv[id][o<<1],minv[id][o<<1|1]);
    }

    void update(int o,int L,int R,int ql,int qr,int subl,int subr,int v){
        if(ql<=L&&qr>=R){
            updateSub(1,1,M,subl,subr,o,v,1);
            return;
        }
        int mid=L+(R-L)/2;
        if(ql<=mid) update(o<<1,L,mid,ql,qr,subl,subr,v);
        if(qr>mid) update(o<<1|1,mid+1,R,ql,qr,subl,subr,v);
        updateSub(1,1,M,subl,subr,o,v,0);
    }

    void querySub(int o,int L,int R,int ql,int qr,int id){
        if(ql<=L&&qr>=R){
            ansMax=max(ansMax,maxv[id][o]);
            ansMin=min(ansMin,minv[id][o]);
            return;
        }
        int mid=L+(R-L)/2;
        if(ql<=mid) querySub(o<<1,L,mid,ql,qr,id);
        if(qr>mid) querySub(o<<1|1,mid+1,R,ql,qr,id);
    }

    void query(int o,int L,int R,int ql,int qr,int subl,int subr){
        if(ql<=L&&qr>=R){
            querySub(1,1,M,subl,subr,o);
            return;
        }
        int mid=L+(R-L)/2;
        if(ql<=mid) query(o<<1,L,mid,ql,qr,subl,subr);
        if(qr>mid) query(o<<1|1,mid+1,R,ql,qr,subl,subr);
    }
}tree;

int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&N,&M)!=EOF){
        tree.clear();
        int t;
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++){
                scanf("%d",&t);
                tree.update(1,1,N,i,i,j,j,t);
            }
        int x1,y1,x2,y2,v;
        char str[10];
        scanf("%d",&Q);
        while(Q--){
            ansMax=-INF,ansMin=INF;
            scanf("%s",str);
            if(str[0]=='c'){
                scanf("%d%d%d",&x1,&y1,&v);
                tree.update(1,1,N,x1,x1,y1,y1,v);
            }
            else{
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                tree.query(1,1,N,x1,x2,y1,y2);
                printf("%d %d\n",ansMax,ansMin);
            }
        }
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Uva 11297 Census(二维线段树)

题意:给出一个n×n的矩阵,有两个操作:查询某个子矩阵的最大值和最小值,将矩阵中的一个数修改为v。 思路:比较裸的二维线段树,但是以前没写过。其实和一维线段树差不多,大概就是按x建一棵线段树,然后对...

UVA11297--Census(二维线段树)

Description This year, there have been many problems with population calculations, since in some ci...

二维线段树UVA11297

#include #include #include #include using namespace std; #define nn 505 #define inf 0x7fffffff int m...

【uva12345】dynamic len 树状数组套线段树

原题传送门 In python, we can use len(start(a[L:R])) to calculate the number of distinct values of elemen...

线段树代码

  • 2014-09-11 12:03
  • 26KB
  • 下载

uva 1400 Ray, Pass me the dishes!(线段树, 分治法求最大连续和)

参照RJ大大的代码写的。非常经典的一题!!!
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)