【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);
        }
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CreationAugust/article/details/51231950

[IMO原题] BZOJ 4915 简单的数字题

第52届IMO试题解答 #include #include using namespace std;int main(){ long long l,r; cin>>l>>r; c...
  • u014609452
  • u014609452
  • 2017-06-01 21:28:24
  • 431

BZOJ2683简单题

Description你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令参数限制内容1 x y A1...
  • KenxHe
  • KenxHe
  • 2017-01-10 15:36:39
  • 185

BZOJ4066: 简单题

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

[bzoj4066]简单题 解题报告

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

POJ1195/BZOJ1176 题解,CDQ分治

POJ1195 MOBILE/ BZOJ 1176 这两个题题意完全相同,放在一起说吧 题意: 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命...
  • qyfl806
  • qyfl806
  • 2017-03-16 14:07:16
  • 271

BZOJ 2683 简单题(CDQ分治+容斥)

Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 1 x y A(1...
  • V5ZSQ
  • V5ZSQ
  • 2016-04-07 10:58:40
  • 498

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

Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:   命令 参数限制 内容 ...
  • sunshinezff
  • sunshinezff
  • 2016-04-23 15:07:17
  • 443

[bzoj4066]简单题

4066: 简单题Time Limit: 50 Sec Memory Limit: 20 MB Submit: 1563 Solved: 420 [Submit][Status][Discus...
  • FZHvampire
  • FZHvampire
  • 2016-04-23 10:24:44
  • 285

[NOIP2010] 乌龟棋 解题报告

[NOIP2010] 乌龟棋 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数)。棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家...
  • Janis_z
  • Janis_z
  • 2016-07-20 20:33:04
  • 834

BZOJ 2287 DP+容斥

思路: 先处理出来f[j]表示这i个物品都可用 填满容量j的方案数容斥一发处理出来g[j]=g[j-w[i]] 表示i不能用的时候 填满容量j的方案数//By SiriusRen #include...
  • qq_31785871
  • qq_31785871
  • 2017-02-17 19:46:14
  • 446
收藏助手
不良信息举报
您举报文章:【BZOJ4066】简单题
举报原因:
原因补充:

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