• 【BZOJ2683】简单题 [分治][树状数组]


    简单题

    Time Limit: 50 Sec  Memory Limit: 128 MB
    [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。

    Solution

      首先把询问拆成4个,那么我们就只要维护一个点左下角权值和了。

      然后对所有操作按照 x 升序排序。

      对 y 用个树状数组前缀和,(由于 x 升序,所以此时询问已经相当于对y求前缀和了)

      以mid为分界线,考虑左区间对右区间的影响

      显然,我们可以把左区间的修改执行,然后执行右区间的询问

      这样我们就做完了这道题。

    Code

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cmath>
      8 using namespace std;
      9 typedef long long s64;
     10  
     11 const int ONE = 1000005;
     12 const int INF = 214748340;
     13  
     14 int get()
     15 {
     16         int res = 1, Q = 1; char c;
     17         while( (c = getchar()) < 48 || c > 57)
     18             if(c == '-') Q = -1;
     19         if(Q) res = c - 48;
     20         while( (c = getchar()) >= 48 && c <= 57)
     21             res = res * 10 + c - 48;
     22         return res * Q;
     23 }
     24  
     25 int n;
     26 namespace BIT
     27 {
     28         int C[ONE];
     29         int lowbit(int i) {return i & -i;}
     30         void Add(int R, int x)
     31         {
     32             for(int i = R; i <= n; i += lowbit(i))
     33                 C[i] += x;
     34         }
     35         int Query(int R)
     36         {
     37             int res = 0;
     38             for(int i = R; i >= 1; i -= lowbit(i))
     39                 res += C[i];
     40             return res;
     41         }
     42 }
     43  
     44 int id, query_num, Ans[ONE];
     45 struct power
     46 {
     47         int id, opt, from;
     48         int x, y, val;
     49 }oper[ONE], q[ONE];
     50  
     51 bool cmp(const power &a, const power &b)
     52 {
     53         if(a.x != b.x) return a.x < b.x;
     54         return a.opt < b.opt;
     55 }
     56  
     57 void Deal(int x_1, int y_1, int x_2, int y_2)
     58 {
     59         query_num++;
     60         oper[++id] = (power){id, 2, query_num, x_2, y_2, 1};
     61         oper[++id] = (power){id, 2, query_num, x_1 - 1, y_1 - 1, 1};
     62         oper[++id] = (power){id, 2, query_num, x_1 - 1, y_2, -1};
     63         oper[++id] = (power){id, 2, query_num, x_2, y_1 - 1, -1};
     64 }
     65  
     66 void Solve(int l, int r)
     67 {
     68         if(l >= r) return;
     69          
     70         int mid = l + r >> 1;
     71         for(int i = l; i <= r; i++)
     72         {
     73             if(oper[i].opt == 1 && oper[i].id <= mid)
     74                 BIT::Add(oper[i].y, oper[i].val);
     75             if(oper[i].opt == 2 && oper[i].id > mid)
     76                 Ans[oper[i].from] += BIT::Query(oper[i].y) * oper[i].val;
     77         }
     78          
     79         for(int i = l; i <= r; i++)
     80             if(oper[i].opt == 1 && oper[i].id <= mid)
     81                 BIT::Add(oper[i].y, -oper[i].val);
     82          
     83         int tl = l, tr = mid + 1;
     84         for(int i = l; i <= r; i++)
     85             if(oper[i].id <= mid) q[tl++] = oper[i];
     86             else q[tr++] = oper[i];
     87          
     88         for(int i = l; i <= r; i++)
     89             oper[i] = q[i];
     90          
     91         Solve(l, mid), Solve(mid + 1, r);
     92 }
     93  
     94 int opt, x_1, y_1, x_2, y_2;
     95  
     96 int main()
     97 {
     98         n = get();
     99         for(;;)
    100         {
    101             opt = get();
    102             if(opt == 3) break;
    103             if(opt == 1)
    104                 oper[++id].id = id, oper[id].opt = 1,
    105                 oper[id].x = get(), oper[id].y = get(), oper[id].val = get();
    106             if(opt == 2)
    107                 x_1 = get(), y_1 = get(),
    108                 x_2 = get(), y_2 = get(),
    109                 Deal(x_1, y_1, x_2, y_2);
    110         }
    111          
    112         sort(oper + 1, oper + id + 1, cmp);
    113          
    114         Solve(1, id);
    115          
    116         for(int i = 1; i <= query_num; i++)
    117             printf("%d
    ", Ans[i]);
    118 }
    View Code
  • 相关阅读:
    JavaScript作用域闭包(你不知道的JavaScript)
    Python笔记---错误笔记
    Go语言核心之美 1.5-作用域
    Android经常使用自己定义控件(二)
    Java开发者最经常使用19个Linux命令
    Python: scikit-image binary descriptor
    android 自己定义状态栏和导航栏分析与实现
    程序猿增加新团队的那些坑
    LeetCode 06 ZigZag Conversion
    【UWP通用应用开发】控件、应用栏
  • 原文地址:https://www.cnblogs.com/BearChild/p/7800833.html
Copyright © 2020-2023  润新知