zoukankan      html  css  js  c++  java
  • BZOJ 2683: 简单题

    2683: 简单题

    Time Limit: 50 Sec  Memory Limit: 128 MB
    Submit: 913  Solved: 379
    [Submit][Status][Discuss]

    Description

    你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

    命令

    参数限制

    内容

    1 x y A

    1<=x,y<=N,A是正整数

    将格子x,y里的数字加上A

    2 x1 y1 x2 y2

    1<=x1<= x2<=N

    1<=y1<= y2<=N

    输出x1 y1 x2 y2这个矩形内的数字和

    3

    终止程序

    Input

    输入文件第一行一个正整数N。
    接下来每行一个操作。
     

    Output

    对于每个2操作,输出一个对应的答案。
     

    Sample Input

    4
    1 2 3 3
    2 1 1 3 3
    1 2 2 2
    2 2 2 3 4
    3

    Sample Output

    3
    5

    HINT

    1<=N<=500000,操作数不超过200000个,内存限制20M。

    对于100%的数据,操作1中的A不超过2000。

    Source

     
    [Submit][Status][Discuss]

    分析

    离线CDQ分治,对于预处理后的所有操作(查询)按照X坐标排序,然后用树状数组维护Y坐标上的前缀和。

    代码

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 const int N = 500005;
      6 const int M = 200005;
      7 
      8 template <class T>
      9 __inline void read(T &x)
     10 {
     11     x = 0; 
     12     bool f = false;
     13     char c = getchar();
     14     
     15     while (c < '0')
     16     {
     17         if (c == '-')
     18             f ^= true;
     19         c = getchar();
     20     }
     21     
     22     while (c >= '0')
     23     {
     24         x = x*10 + c - '0';
     25         c = getchar();
     26     }
     27     
     28     if (f)x = -x;
     29 }
     30 
     31 struct operation
     32 {
     33     int id, op, to, x, y, d;
     34 }q[M << 2], tmp[M << 2];
     35 
     36 int cmp(const void *a, const void *b)
     37 {
     38     operation *A = (operation *)a;
     39     operation *B = (operation *)b;
     40     
     41     if (A->x != B->x)
     42         return A->x - B->x;
     43     if (A->y != B->y)
     44         return A->y - B->y;
     45     return A->op - B->op;
     46 }
     47 
     48 int n, m, t;
     49 
     50 void pushQuery(void)
     51 {
     52     int x1; read(x1);
     53     int y1; read(y1);
     54     int x2; read(x2);
     55     int y2; read(y2);
     56     
     57     ++t;
     58     {
     59         ++m; 
     60         q[m].d = 1;
     61         q[m].op = 2;
     62         q[m].id = m; 
     63         q[m].to = t; 
     64         q[m].x = x1 - 1;
     65         q[m].y = y1 - 1;
     66     }
     67     {
     68         ++m;
     69         q[m].d = 1;
     70         q[m].op = 2;
     71         q[m].id = m;
     72         q[m].to = t;
     73         q[m].x = x2;
     74         q[m].y = y2;
     75     }
     76     {
     77         ++m;
     78         q[m].d = -1;
     79         q[m].op = 2;
     80         q[m].id = m;
     81         q[m].to = t;
     82         q[m].y = y2;
     83         q[m].x = x1 - 1;
     84     }
     85     {
     86         ++m;
     87         q[m].d = -1;
     88         q[m].op = 2;
     89         q[m].id = m;
     90         q[m].to = t;
     91         q[m].x = x2;
     92         q[m].y = y1 - 1;
     93     }
     94 }
     95 
     96 int answer[M];
     97 
     98 void printAnswer(void)
     99 {
    100     for (int i = 1; i <= t; ++i)
    101         printf("%d
    ", answer[i]);
    102 }
    103 
    104 namespace binaryInsertTree
    105 {
    106     int tree[N];
    107     
    108     void change(int p, int v)
    109     {
    110         for (int i = p; i <= n; i += i & -i)
    111             tree[i] += v;
    112     }
    113     
    114     int query(int p)
    115     {
    116         int ret = 0;
    117         
    118         for (int i = p; i >= 1; i -= i & -i)
    119             ret += tree[i];
    120         
    121         return ret;
    122     }
    123 }
    124 
    125 void divideAndConquer(int l, int r)
    126 {
    127     if (l != r)
    128     {
    129         int mid = (l + r) >> 1;
    130         
    131         for (int i = l; i <= r; ++i)
    132         {
    133             if (q[i].op == 1 && q[i].id <= mid)
    134                 binaryInsertTree::change(q[i].y, q[i].d);
    135             if (q[i].op == 2 && q[i].id > mid)
    136                 answer[q[i].to] += binaryInsertTree::query(q[i].y) * q[i].d;
    137         }
    138         
    139         for (int i = l; i <= r; ++i)
    140             if (q[i].op == 1 && q[i].id <= mid)
    141                 binaryInsertTree::change(q[i].y, -q[i].d);
    142         
    143         int t1 = l, t2 = mid + 1;
    144         
    145         for (int i = l; i <= r; ++i)
    146         {
    147             if (q[i].id <= mid)
    148                 tmp[t1++] = q[i];
    149             else
    150                 tmp[t2++] = q[i];
    151         }
    152         
    153         for (int i = l; i <= r; ++i)
    154             q[i] = tmp[i];
    155             
    156         divideAndConquer(l, mid);
    157         divideAndConquer(mid + 1, r);
    158     }
    159 }
    160 
    161 signed main(void)
    162 {
    163     read(n);
    164     
    165     for (m = t = 0; ; )
    166     {
    167         int opt; read(opt);
    168         
    169         if (opt == 3)break;
    170         
    171         switch (opt)
    172         {
    173             case 1 :
    174                 ++m;
    175                 q[m].op = 1;
    176                 q[m].id = m;
    177                 read(q[m].x);
    178                 read(q[m].y);
    179                 read(q[m].d);
    180                 break;
    181             case 2 :
    182                 pushQuery();
    183         }
    184     }
    185     
    186     qsort(q + 1, m, sizeof(operation), cmp);
    187     
    188     divideAndConquer(1, m);
    189     
    190     printAnswer();
    191 }
    BZOJ_2683.cpp

    @Author: YouSiki

  • 相关阅读:
    如何使用dom拼接xml字符串(标准方式)
    javascript默认将数字类型的“002,00123”,作为整数,去掉前面的0
    java学习小记
    如何将div排成一行显示(默认垂直显示)
    【转】JDBC调用存储过程之实例讲解
    数组求和算法系列
    《12个球问题》分析
    C#类在什么时候分配内存
    C++请不要问我string s=”a”+”b”分配了几次内存
    算法两道百度笔试题
  • 原文地址:https://www.cnblogs.com/yousiki/p/6073551.html
Copyright © 2011-2022 走看看