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

    4066: 简单题

    Time Limit: 50 Sec  Memory Limit: 20 MB
    Submit: 2373  Solved: 622
    [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。
    接下来每行一个操作。每条命令除第一个数字之外,
    均要异或上一次输出的答案last_ans,初始时last_ans=0。
     

    Output

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

    Sample Input

    4
    1 2 3 3
    2 1 1 3 3
    1 1 1 1
    2 1 1 0 7
    3

    Sample Output

    3
    5

    HINT

    数据规模和约定

    1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。

    样例解释见OJ2683

     

    新加数据一组,但未重测----2015.05.24

     

    Source

    [Submit][Status][Discuss]

    记得BZOJ还有两道题和这个题是一个意思,但是略有不同。

    这道题有两个地方需要注意:

    1. 数据通过一定方式强制在线

    2. 内存限制只有20M,二维数据结构基本被终结

    显然是KD-Tree了,而且需要定期重建以保持其优秀的性质。看到有的题解没有重建就AC了,大概新加数据有卡这类程序,亦或者是大佬的KD-Tree十分优美吧,我等蒟蒻并无此功底……

    因为数据以3作为输入终止信号,一开始并不知道有多少操作,也不知道操作是什么,我也懒得先存起来统计操作次数,所以需要找一个合适的重建限度,及进行多少次插入操作后,重建整个KD-Tree。要来数据在本地试了几个数字,发现这个限度取1500~2000较为合适(我一开始猜了个500,直接TLE了),虽然OJ和本地的测试环境有些差距吧,但还是可以作为参考,小伙伴可以像我一样取1700,OJ上跑了30S。

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 inline int getint(void)
      5 {
      6     int r = 0, f = 0, c = getchar();
      7 
      8     for (; c < 48; c = getchar())
      9         if (c == '-')f ^= 1;
     10     
     11     for (; c > 47; c = getchar())
     12         r = r * 10 + c - 48;
     13     
     14     return f ? -r : r;
     15 }
     16 
     17 const int siz = 200005;
     18 
     19 struct node
     20 {
     21     int val;
     22     int sum;
     23     int pos[2];
     24     int son[2];
     25     int mini[2];
     26     int maxi[2];
     27 
     28     inline void setup(int x, int y, int v)
     29     {
     30         val = sum = v;
     31         son[0] = son[1] = 0;
     32         pos[0] = mini[0] = maxi[0] = x;
     33         pos[1] = mini[1] = maxi[1] = y;
     34     }
     35 }tr[siz]; int tot;
     36 
     37 inline void update(int t)
     38 {
     39     tr[t].sum = tr[t].val;
     40 
     41     if (tr[t].son[0])
     42         tr[t].sum += tr[tr[t].son[0]].sum;
     43     if (tr[t].son[1])
     44         tr[t].sum += tr[tr[t].son[1]].sum;
     45 
     46     tr[t].mini[0] = tr[t].maxi[0] = tr[t].pos[0];
     47     tr[t].mini[1] = tr[t].maxi[1] = tr[t].pos[1];
     48 
     49     for (int i = 0; i < 2; ++i)if (tr[t].son[i])
     50         for (int j = 0; j < 2; ++j)
     51         {
     52             if (tr[t].mini[j] > tr[tr[t].son[i]].mini[j])
     53                 tr[t].mini[j] = tr[tr[t].son[i]].mini[j];
     54             if (tr[t].maxi[j] < tr[tr[t].son[i]].maxi[j])
     55                 tr[t].maxi[j] = tr[tr[t].son[i]].maxi[j];
     56         }
     57 }
     58 
     59 void insert(int &t, int p, int k)
     60 {
     61     if (!t)t = p;
     62     else
     63     {
     64         if (tr[p].pos[k] <= tr[t].pos[k])
     65             insert(tr[t].son[0], p, k ^ 1);
     66         else 
     67             insert(tr[t].son[1], p, k ^ 1);
     68         
     69         update(t);
     70     }
     71 }
     72 
     73 int cmpk;
     74 
     75 inline bool cmp(const node &a, const node &b)
     76 {
     77     if (a.pos[cmpk] != b.pos[cmpk])
     78         return a.pos[cmpk] < b.pos[cmpk];
     79     else
     80         return a.pos[cmpk^1] < b.pos[cmpk^1];
     81 }
     82 
     83 int build(int l, int r, int k)
     84 {
     85     int mid = (l + r) >> 1; cmpk = k;
     86     
     87     std::nth_element(tr + l, tr + mid, tr + r + 1, cmp);
     88     
     89     tr[mid].son[0] = l < mid ? build(l, mid - 1, k ^ 1) : 0;
     90     tr[mid].son[1] = r > mid ? build(mid + 1, r, k ^ 1) : 0;
     91     
     92     return update(mid), mid;
     93 }
     94 
     95 int x1, y1, x2, y2, ans;
     96 
     97 inline bool none(int t)
     98 {
     99     return 
    100         x1 > tr[t].maxi[0]
    101     ||  x2 < tr[t].mini[0]
    102     ||  y1 > tr[t].maxi[1]
    103     ||  y2 < tr[t].mini[1];
    104 }
    105 
    106 inline bool have(int t)
    107 {
    108     return 
    109         x1 <= tr[t].mini[0]
    110     &&  x2 >= tr[t].maxi[0]
    111     &&  y1 <= tr[t].mini[1]
    112     &&  y2 >= tr[t].maxi[1];
    113 }
    114 
    115 inline bool in(int t)
    116 {
    117     return
    118         x1 <= tr[t].pos[0]
    119     &&  x2 >= tr[t].pos[0]
    120     &&  y1 <= tr[t].pos[1]
    121     &&  y2 >= tr[t].pos[1];
    122 }
    123 
    124 void query(int t)
    125 {
    126     if (none(t))return;
    127     if (have(t))ans += tr[t].sum;
    128     else
    129     {
    130         if (in(t))ans += tr[t].val;
    131         if (tr[t].son[0])query(tr[t].son[0]);
    132         if (tr[t].son[1])query(tr[t].son[1]);
    133     }
    134 }
    135 
    136 signed main(void)
    137 {
    138 //    freopen("simple.in", "r", stdin);
    139 //    freopen("simple.out", "w", stdout); 
    140     
    141     int n = getint(), root = ++tot;
    142 
    143     tr[root].setup(n >> 1, n >> 1, 0);
    144 
    145     while (true)
    146     {
    147         int k = getint();
    148 
    149         if (k == 1)
    150         {
    151             int x = getint() ^ ans;
    152             int y = getint() ^ ans;
    153             int v = getint() ^ ans;
    154             
    155             tr[++tot].setup(x, y, v);
    156             
    157             if (tot % 1700)
    158                 insert(root, tot, 0);
    159             else
    160                 root = build(1, tot, 0);
    161         }
    162         else if (k == 2)
    163         {
    164             x1 = getint() ^ ans;
    165             y1 = getint() ^ ans;
    166             x2 = getint() ^ ans;
    167             y2 = getint() ^ ans;
    168             
    169             ans = 0; query(root);
    170 
    171             printf("%d
    ", ans);
    172         }
    173         else break;
    174     }
    175     
    176 //    fclose(stdin);
    177 //    fclose(stdout);
    178 }
    179 
    180 /*
    181 2000 : 18.02
    182 1800 : 17.22
    183 1700 : 16.89
    184 1500 : 17.74
    185 1000 : 20.80
    186 900  : 22.53
    187 700  : 25.08
    188 500  : 33.55
    189 300  : T L E
    190 */

    @Author: YouSiki

  • 相关阅读:
    获取腾讯soso地图坐标代码
    PHP获取服务器的mac地址类
    关于PHPExcel导出Excel时身份证,数字会导出为科学计数的处理方法
    PhpExcel笔记,phpExcel中文帮助手册
    微信开发之——Php批量生成带参数的二维码
    [转载]数据管理——数据血缘关系概述
    HDFS学习总结
    CDH5.7Hadoop集群搭建(离线版)
    QlikSense系列(1)——整体介绍
    Python学习小计
  • 原文地址:https://www.cnblogs.com/yousiki/p/6285500.html
Copyright © 2011-2022 走看看