zoukankan      html  css  js  c++  java
  • BZOJ4066 简单题

     

    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
     
    数据规模和约定

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

     

     

    正解:kd-tree

     

    解题报告:

       大概题意是给你一个二维的图,每次给一个点加上一个数,查询某个矩阵中的和,强制在线

           kd-tree第二发题,又是一道模板水题  kd-tree最喜欢的强制在线。其实如果可以离线的话我可以用整体二分。

           回到正题,一看数据范围n<=500000,操作数<=200000,显然500000*500000的空间是很令人愉快的,所以另辟蹊径。

       根据kd-tree思想,我们划分二维空间,搞出一棵神奇的二维二叉搜索树(kd-tree的本质),每次插入结点就直接按二叉搜索树的规则插入,查询也是按二叉搜索树的规则来查询。然而注意到这种做法在这道题是可以被卡的,比如说全挂在了一边,退化成链(变态出题人)

          所以我们可以每插入5000个结点就重构一次树,把树的形态重新改变一下,这样就可以保证复杂度了。在BZOJ上跑得太慢了,只有rank50多。

          具体实现看代码。

     

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #ifdef WIN32   
     13 #define OT "%I64d"
     14 #else
     15 #define OT "%lld"
     16 #endif
     17 using namespace std;
     18 typedef long long LL;
     19 const int MAXN = 200011;
     20 const int MOD = 5000;
     21 int n,m;
     22 int ans;
     23 int k1,k2,val;
     24 int lx,ly,rx,ry;
     25 int root;
     26 int nowD;
     27 
     28 struct node{
     29     int d[2],Min[2],Max[2];
     30     int sum,w;
     31     int ch[2];
     32 }t[MAXN];
     33 
     34 inline int getint()
     35 {
     36        int w=0,q=0;
     37        char c=getchar();
     38        while((c<'0' || c>'9') && c!='-') c=getchar();
     39        if (c=='-')  q=1, c=getchar();
     40        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     41        return q ? -w : w;
     42 }
     43 
     44 inline void update(int now){
     45     t[now].sum=t[now].w;
     46     for(int i=0;i<=1;i++) {
     47     if(t[now].ch[i]) {
     48         t[now].sum+=t[ t[now].ch[i] ].sum;
     49         if(t[ t[now].ch[i] ].Min[0] < t[now].Min[0]) t[now].Min[0]=t[ t[now].ch[i] ].Min[0];
     50         if(t[ t[now].ch[i] ].Max[0] > t[now].Max[0]) t[now].Max[0]=t[ t[now].ch[i] ].Max[0];
     51         if(t[ t[now].ch[i] ].Min[1] < t[now].Min[1]) t[now].Min[1]=t[ t[now].ch[i] ].Min[1];
     52         if(t[ t[now].ch[i] ].Max[1] > t[now].Max[1]) t[now].Max[1]=t[ t[now].ch[i] ].Max[1];
     53     }
     54     }
     55 }
     56 
     57 inline void kd_insert(int root,int D){
     58     int direc=(t[n].d[D]>t[root].d[D]);
     59     if(t[root].ch[direc]) kd_insert(t[root].ch[direc],D^1);
     60     else t[root].ch[direc]=n;
     61     update(root);
     62 }
     63 
     64 inline void kd_query(int now){
     65     if(t[now].d[0]>=lx && t[now].d[1]>=ly && t[now].d[0]<=rx && t[now].d[1]<=ry) ans+=t[now].w;
     66     for(int i=0;i<=1;i++) {
     67     if(t[now].ch[i]){
     68         if(t[t[now].ch[i]].Min[0]<=rx&&t[t[now].ch[i]].Max[0]>=lx&&t[t[now].ch[i]].Min[1]<=ry&&t[t[now].ch[i]].Max[1]>=ly) {
     69             if(t[t[now].ch[i]].Max[0]<=rx && t[t[now].ch[i]].Min[0]>=lx && t[t[now].ch[i]].Max[1]<=ry && t[t[now].ch[i]].Min[1]>=ly)   ans+=t[t[now].ch[i]].sum;
     70             else kd_query(t[now].ch[i]);
     71         } 
     72     }
     73     }
     74 }
     75 
     76 inline bool cmp(node q,node qq){
     77     if(q.d[nowD]==qq.d[nowD]) return q.d[nowD^1]<qq.d[nowD^1]; 
     78     return q.d[nowD]<qq.d[nowD];
     79 }
     80 
     81 inline int rebuild(int l,int r,int D){
     82     int mid=(l+r)/2; nowD=D;
     83     nth_element(t+l+1,t+mid+1,t+r+1,cmp);
     84     //t[mid].sum=t[mid].w; 
     85     t[mid].Min[0]=t[mid].Max[0]=t[mid].d[0]; t[mid].Min[1]=t[mid].Max[1]=t[mid].d[1];
     86     if(l!=mid) t[mid].ch[0]=rebuild(l,mid-1,D^1);
     87     if(mid!=r) t[mid].ch[1]=rebuild(mid+1,r,D^1);
     88     update(mid);
     89     return mid;
     90 }
     91 
     92 inline void solve(){
     93     int ljh;  root=1;
     94     while(1){
     95     ljh=getint();
     96     if(ljh==3) break;
     97     else if(ljh==1) {
     98         k1=getint();k2=getint();val=getint();
     99         k1=k1^ans; k2=k2^ans; val=val^ans;
    100         n++;  t[n].Min[0]=t[n].Max[0]=t[n].d[0]=k1; t[n].Min[1]=t[n].Max[1]=t[n].d[1]=k2; t[n].w=t[n].sum=val;     
    101         if(n>1){        
    102         if(n%MOD==0) {
    103             for(int i=1;i<=n;i++) t[i].ch[0]=t[i].ch[1]=0;
    104             root=rebuild(1,n,0);
    105         }
    106         else
    107             kd_insert(root,0);
    108         }
    109     }
    110     else {
    111         lx=getint();ly=getint();rx=getint();ry=getint();
    112         lx=lx^ans; ly=ly^ans; rx=rx^ans; ry=ry^ans;
    113         ans=0;
    114         if(n)
    115         kd_query(root);
    116         printf("%d
    ",ans);
    117     }
    118     }
    119 }
    120 
    121 int main()
    122 {
    123   m=getint();  solve();
    124   return 0;
    125 }
  • 相关阅读:
    安卓学习-activity-窗体调用和传参
    安卓学习-activity-PreferenceActivity
    安卓学习-activity-ExpandableListActivity
    安卓学习-activity-LauncherActivity
    安卓学习-界面-事件-AsyncTask
    安卓学习-界面-事件-handler
    安卓学习-界面-事件-Configuration
    安卓学习-界面-ui-菜单ActionBar
    安卓学习-界面-ui-普通菜单
    C++实现成绩管理模拟系统
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5524785.html
Copyright © 2011-2022 走看看