zoukankan      html  css  js  c++  java
  • 10.25T2 二维线段树

    Description

      为了准备校庆庆典,学校招募了一些学生组成了一个方阵,准备在庆典上演出。
      这个方阵是一个n*m的矩形,第i行第j列有一名学生,他有一个能力值Ai,j。
      校长会定期检查一个p*q的方阵,询问这个方阵的学生能力值之和,或是学生能力值的最大值,或是学生能力值的最小值。由于校长不喜欢一个方阵长宽之比差太多,他每次询问的方阵的长不会超过宽的两倍。作为校庆筹办组组长的你,应该迅速并准确的回答校长所问的问题。

    Input

      第一行包含两个整数n,m,表示这个方阵的两条边的长度。
      接下来n行,每行m个数,表示每个学生的能力值。
      接下来一行包含一个整数q,表示校长的询问数。
      接下来q行,每行先一个字符串s,接下来4个整数x1,y1,x2,y2,保证x1≤x2,y1≤y2,设以第x1行y1列为左上角,第x2行y2列为右下角的方阵为P。(本题为0下标)
      若字符串内容为“SUM”,请求出P中所有学生的能力值之和。
      若字符串内容为“MAX”,请求出P中所有学生的能力值的最大值。
      若字符串内容为“MIN”,请求出P中所有学生的能力值的最小值。

    Output

      输出总共q行,第i行的数为第i组询问对应的答案ansi。

    Sample Input

    3 3 1 2 3 4 5 6 7 8 9 3 SUM 0 0 1 1 MAX 0 0 2 2 MIN 0 1 1 1

    Sample Output

    12 9 2

    Hint

    【样例解释】
      对于第一组询问,能力值之和为1+2+4+5=12。
      对于第二组询问,能力值最大的位置为第2行第2列。
      对于第三组询问,能力值最小的位置为第0行第1列。
    【数据规模和约定】
      对于40%的数据,n,m≤200,q≤200
      对于60%的数据,n,m≤300,q≤100000
      对于80%的数据,n,m≤500,q≤500000
      对于100%的数据,n,m≤800,q≤500000,0≤Aij≤3000,每个询问的方阵的长不超过宽的两倍。
     
     
     
     
    二维线段树的板子。。。emmmm(好难写啊)
    code:
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<string>
      4 #define lc (p<<1)
      5 #define rc (p<<1|1)
      6 #define N 3301
      7 #define max(i,j) i>j?i:j
      8 #define min(i,j) i<j?i:j
      9 using namespace std;
     10 const int inf=0x3f3f3f3f;
     11 int MAX=0,MIN=9999999;
     12 int n,m;
     13 int g[801][801],sum[801][801];
     14 struct segY {
     15     struct node {
     16         int l,r,min,max;
     17         node() {
     18             min=9999999;
     19         }
     20     } t[N];
     21     int up,down;
     22     void pushup(int p) {
     23         t[p].max=max(t[lc].max,t[rc].max);
     24         t[p].min=min(t[lc].min,t[rc].min);
     25     }
     26     void build(int p,int l,int r) {
     27         t[p].l=l,t[p].r=r;
     28         if(l==r) {
     29             for(int i=down; i<=up; i++)t[p].max=max(t[p].max,g[i][l]),t[p].min=min(t[p].min,g[i][l]);
     30             return;
     31         }
     32         int mid=l+r>>1;
     33         build(lc,l,mid);
     34         build(rc,mid+1,r);
     35         pushup(p);
     36     }
     37     int query_max(int p,int ql,int qr) {
     38         if(ql<=t[p].l&&t[p].r<=qr) {
     39             return t[p].max;
     40         }
     41         int a1=0,a2=0;
     42         int mid=t[p].l+t[p].r>>1;
     43         if(ql<=mid)a1=query_max(lc,ql,qr);
     44         if(qr>mid)a2=query_max(rc,ql,qr);
     45         return a1>a2?a1:a2;
     46     }
     47     int query_min(int p,int ql,int qr) {
     48         if(ql<=t[p].l&&t[p].r<=qr) {
     49             return t[p].min;
     50         }
     51         int a1=inf,a2=inf;
     52         int mid=t[p].l+t[p].r>>1;
     53         if(ql<=mid)a1=query_min(lc,ql,qr);
     54         if(qr>mid)a2=query_min(rc,ql,qr);
     55         return a1>a2?a2:a1;
     56     }
     57 };
     58 struct segX {
     59     int l,r;
     60     segY Y;
     61 } t[800*4];
     62 void Build(int p,int l,int r) {
     63     t[p].l=l,t[p].r=r;
     64     t[p].Y.down=l,t[p].Y.up=r;
     65     t[p].Y.build(1,1,m);
     66     if(l==r)return;
     67     int mid=l+r>>1;
     68     Build(lc,l,mid);
     69     Build(rc,mid+1,r);
     70 }
     71 int Query_min(int p,int x1,int y1,int x2,int y2) {
     72     if(x1<=t[p].l&&t[p].r<=x2) {
     73         return t[p].Y.query_min(1,y1,y2);
     74     }
     75     int a1=inf,a2=inf;
     76     int mid=t[p].l+t[p].r>>1;
     77     if(x1<=mid)a1=Query_min(lc,x1,y1,x2,y2);
     78     if(x2>mid)a2=Query_min(rc,x1,y1,x2,y2);
     79     return a1>a2?a2:a1;
     80 }
     81 int Query_max(int p,int x1,int y1,int x2,int y2) {
     82     if(x1<=t[p].l&&t[p].r<=x2) {
     83         return t[p].Y.query_max(1,y1,y2);
     84     }
     85     int a1=0,a2=0;
     86     int mid=t[p].l+t[p].r>>1;
     87     if(x1<=mid)a1=Query_max(lc,x1,y1,x2,y2);
     88     if(x2>mid)a2=Query_max(rc,x1,y1,x2,y2);
     89     return a1<a2?a2:a1;
     90 }
     91 long long read() {
     92     long long x=0,f=1;
     93     char c=getchar();
     94     while(!isdigit(c)) {
     95         if(c=='-')f=-1;
     96         c=getchar();
     97     }
     98     while(isdigit(c)) {
     99         x=(x<<3)+(x<<1)+c-'0';
    100         c=getchar();
    101     }
    102     return x*f;
    103 }
    104 int main() {
    105     n=read(),m=read();
    106     for(int i=1; i<=n; i++) {
    107         for(int j=1; j<=m; j++) {
    108             g[i][j]=read();
    109             sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j];
    110         }
    111     }
    112     Build(1,1,n);
    113     int Q;
    114     Q=read();
    115     char opt[5];
    116     while(Q--) {
    117         scanf("%s",opt);
    118         if(opt[1]=='U') {
    119             int x1,x2,y1,y2;
    120             x1=read(),y1=read(),x2=read(),y2=read();
    121             x1++,x2++,y1++,y2++;
    122             cout<<sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]<<'
    ';
    123         }
    124         if(opt[1]=='A') {
    125             int x1,x2,y1,y2;
    126             x1=read(),y1=read(),x2=read(),y2=read();
    127             x1++,x2++,y1++,y2++;
    128             cout<<Query_max(1,x1,y1,x2,y2)<<'
    ';
    129         }
    130         if(opt[1]=='I') {
    131             int x1,x2,y1,y2;
    132             x1=read(),y1=read(),x2=read(),y2=read();
    133             x1++,x2++,y1++,y2++;
    134             cout<<Query_min(1,x1,y1,x2,y2)<<'
    ';
    135         }
    136     }
    137     return 0;
    138 }

    over

  • 相关阅读:
    【题解】NOIP2016换教室
    【题解】平面最近点对(加强版)
    [atcoder002E] Candy Piles [博弈论]
    [AGC002D] Stamp Rally [并查集+整体二分]
    [ACG001E] BBQ hard [dp]
    [BJOI2006][bzoj1001] 狼抓兔子 [最小割]
    [usaco jan 09] 安全路径 travel [最短路径树]
    [usaco jan 09] 气象牛 baric [dp]
    [poj1741] tree [点分治]
    [NOI2009] 植物大战僵尸 [网络流]
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9852313.html
Copyright © 2011-2022 走看看