【BZOJ4066】简单题

原创 2016年04月24日 08:39:53

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

By wjy1998
补了一波kdtree,发现这是个好东西
当成平衡树或者线段树就行了
4066因为是动态加点的,所以需要隔一些点暴力重构一次
点插入,矩阵求和,裸做

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
#define Dnum 2
#define GET (ch>='0'&&ch<='9')
using namespace std;
int cnt,n,Q,root=1,ans,dx1,dx2,dy1,dy2;
bool cmp_d;
struct Query    {   int opt,X1,Y1,X2,Y2,val;    }q[MAXN];
inline int in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();return x;
}
struct KDtree
{
    int ch[2],w,sum,minn[Dnum],maxn[Dnum],d[Dnum];
    inline void init()  {   for (int i=0;i<Dnum;++i)    minn[i]=maxn[i]=d[i];   sum=w;  }
    inline bool operator < (const KDtree& a)const   {   return d[cmp_d]<a.d[cmp_d]; }
}tree[MAXN];
inline void push_up(int rt)
{
    tree[rt].sum=tree[rt].w;
    for (int i=0;i<Dnum;++i)
        if (tree[rt].ch[i])
        {
            int x=tree[rt].ch[i];
            tree[rt].sum+=tree[x].sum;
            for (int j=0;j<Dnum;++j)
                tree[rt].minn[j]=min(tree[rt].minn[j],tree[x].minn[j]),
                tree[rt].maxn[j]=max(tree[rt].maxn[j],tree[x].maxn[j]);
        }
}
int rebuild(int l=1,int r=n,bool d=0)
{
    cmp_d=d;int mid=(l+r)>>1;nth_element(tree+l,tree+mid,tree+r+1);
    tree[mid].init();
    if (l!=mid) tree[mid].ch[0]=rebuild(l,mid-1,d^1);
    if (r!=mid) tree[mid].ch[1]=rebuild(mid+1,r,d^1);
    return push_up(mid),mid;
}
void insert(int rt=root,bool d=0)
{
    bool flag=(tree[n].d[d]>tree[rt].d[d]);
    if (tree[rt].ch[flag])  insert(tree[rt].ch[flag],d^1);  else    tree[rt].ch[flag]=n;
    push_up(rt);
}
void query(int rt=root)
{
    if (tree[rt].d[0]>=dx1&&tree[rt].d[0]<=dx2&&tree[rt].d[1]>=dy1&&tree[rt].d[1]<=dy2) ans+=tree[rt].w;
    for (int i=0;i<Dnum;++i)
        if (tree[rt].ch[i])
        {
            int x=tree[rt].ch[i];
            if (tree[x].maxn[0]>=dx1&&tree[x].maxn[1]>=dy1&&tree[x].minn[0]<=dx2&&tree[x].minn[1]<=dy2)
            {
                if (tree[x].minn[0]>=dx1&&tree[x].maxn[0]<=dx2&&tree[x].minn[1]>=dy1&&tree[x].maxn[1]<=dy2) ans+=tree[x].sum;
                else    query(x);
            }
        }
}
int main()
{
    in(n);n=0;
    while (in(q[++Q].opt)!=3)
    {
        if (q[Q].opt==1)    in(q[Q].X1),in(q[Q].Y1),in(q[Q].val),++n;
        else    in(q[Q].X1),in(q[Q].Y1),in(q[Q].X2),in(q[Q].Y2);
    }
    int size=(int)sqrt((double)n*log2((double)n));Q--;n=0;
    for (int i=1;i<=Q;i++)
    {
        if (q[i].opt==1)
        {
            ++n;tree[n].d[0]=q[i].X1^ans;tree[n].d[1]=q[i].Y1^ans;tree[n].w=q[i].val^ans;
            tree[n].init();
            if (n>1)    insert();
            if (size==1||size==0||n%size==0)
            {
                for (int j=1;j<=n;++j)  tree[j].ch[0]=tree[j].ch[1]=0;
                rebuild();root=(1+n)>>1;
            }
        }
        else
        {
            dx1=q[i].X1^ans;dx2=q[i].X2^ans;dy1=q[i].Y1^ans;dy2=q[i].Y2^ans;ans=0;
            if (n)  query();printf("%d\n",ans);
        }
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

[bzoj4066]简单题 解题报告

也是很久以前奇葩做法搞的题,补个解题报告。大爷的做法:听说是把k-d树写成替罪的或是每n√\sqrt n重建。 傻逼的做法: 我们是理论计算机科学家(当时我弱不会k-d树。。),所以我们需要思考科...
  • TA201314
  • TA201314
  • 2016年04月22日 17:45
  • 826

BZOJ4066 简单题

强制在线还卡内存,于是上KDT,插入的时候替罪羊式重建,真是tm玄学复杂度 #include #include #include #include #include #include #includ...
  • neither_nor
  • neither_nor
  • 2016年07月13日 20:52
  • 630

BZOJ4066: 简单题

50s卡过..不知道为什么这么慢格子(x,y)里的加A可以直接插入一个值为A的点(x,y),如果原来有这个点了也没关系 因为插入可能导致树不平衡,所以用替罪羊树的重构思想,不满足平衡条件时暴力重构子...
  • L_0_Forever_LF
  • L_0_Forever_LF
  • 2017年03月25日 08:19
  • 583

BZOJ4066: 简单题

题目大意:两个操作,单点修改,矩形求和,强制在线,矩阵边长≤50W 强制在线不能用cdq,所以只能上K-DTREE了,然而这题动态加点,所以每插入一定次数就暴力重建一次,这样时间复杂度大概是...
  • commonc
  • commonc
  • 2016年08月12日 08:36
  • 284

【bzoj4066】简单题

Description你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:命令 参数限制 内容 1 x y A 1...
  • w_yqts
  • w_yqts
  • 2017年05月24日 18:08
  • 126

bzoj4066 简单题

(http://www.elijahqi.win/2018/01/12/bzoj4066-%E7%AE%80%E5%8D%95%E9%A2%98) Description 你有一个N*N的棋盘,每...
  • elijahqi
  • elijahqi
  • 2018年01月12日 01:43
  • 7

【K-D树 求矩阵的和】BZOJ-4066 简单题

Problem Description 输入一个N,代表有一个N*N的棋盘。 有三种操作 1 x y A : 将格子x, y里的数字加上A 2 xl yl xr yr : 输出x...
  • bbbbswbq
  • bbbbswbq
  • 2017年12月01日 11:16
  • 36

[ KD-tree ] BZOJ4066

裸题 #include using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; ...
  • gjghfd
  • gjghfd
  • 2018年01月18日 15:56
  • 10

bzoj4066 简单题

【题意】 n*n网格,初始每个点权值为0,m个操作,共2种: 1.(x,y)点权+z 2.查询矩形(x1,y1)(x2,y2)的点权和 强制在线 【数据范围】 n 【思路】 kd-tr...
  • leolyun
  • leolyun
  • 2016年12月10日 22:33
  • 203

【bzoj4066】【简单题】【kd树】

Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:   命令 参数限制 内容 ...
  • sunshinezff
  • sunshinezff
  • 2016年04月23日 15:07
  • 388
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【BZOJ4066】简单题
举报原因:
原因补充:

(最多只允许输入30个字)