【kd-tree】bzoj1176 [Balkan2007]Mokia

裸题不多说,注意在sqrt(n*log(n))次插入后重构树以保持深度。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 170011
#define KD 2//ά¶ÈÊý
int qp[2][2];
int n,root=1,m;
int Begin;
bool dn;
struct Node
{
    int minn[KD],maxx[KD],p[KD],ch[2];
    int sumv,w;
    void Init()
      {
        for(int i=0;i<KD;++i)
          minn[i]=maxx[i]=p[i];
        sumv=w;
      }
}T[N];
inline void Clear()
{
    for(int i=1;i<=n;++i)
      T[i].ch[0]=T[i].ch[1]=0;
}
inline void Update(int rt)
{
    T[rt].sumv=T[rt].w;
    for(int i=0;i<2;++i)
      if(T[rt].ch[i])
        {
          T[rt].sumv+=T[T[rt].ch[i]].sumv;
          for(int j=0;j<KD;++j)
            {
              T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]);
              T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]);
            }
        }
}
bool operator < (const Node &a,const Node &b){return a.p[dn]<b.p[dn];}
inline int Buildtree(int l=1,int r=n,bool d=0)
{
    dn=d;
    int m=(l+r>>1);
    nth_element(T+l,T+m,T+r+1);
    T[m].Init();
    if(l!=m) T[m].ch[0]=Buildtree(l,m-1,d^1);
    if(m!=r) T[m].ch[1]=Buildtree(m+1,r,d^1);
    Update(m);
    return m;
}
inline void Insert(int rt=root,bool d=0)
{
    bool f=(T[n].p[d]>T[rt].p[d]);
    if(T[rt].ch[f]) Insert(T[rt].ch[f],d^1);
    else T[rt].ch[f]=n;
    Update(rt);
}
int ans;
void Query(int rt=root)
{
    if(T[rt].p[0] >= qp[0][0] && T[rt].p[0] <= qp[1][0]
    && T[rt].p[1] >= qp[0][1] && T[rt].p[1] <= qp[1][1])
      ans+=T[rt].w;
    for(int i=0;i<2;++i)
      if(T[rt].ch[i]
      && T[T[rt].ch[i]].maxx[0] >= qp[0][0] && T[T[rt].ch[i]].minn[0] <= qp[1][0]
      && T[T[rt].ch[i]].maxx[1] >= qp[0][1] && T[T[rt].ch[i]].minn[1] <= qp[1][1])
        {
          if(T[T[rt].ch[i]].minn[0] >= qp[0][0] && T[T[rt].ch[i]].maxx[0] <= qp[1][0]
          && T[T[rt].ch[i]].minn[1] >= qp[0][1] && T[T[rt].ch[i]].maxx[1] <= qp[1][1])
            ans+=T[T[rt].ch[i]].sumv;
          else
            Query(T[rt].ch[i]);
        }
}
int op[N],X1[N],Y1[N],X2[N],Y2[N];
int Vs[N];
int main()
{
//  freopen("data7.in","r",stdin);
//  freopen("bzoj4066.out","w",stdout);
    scanf("%d%d",&Begin,&m); m=0;
    while(1)
      {
        ++m;
        scanf("%d",&op[m]);
        if(op[m]==3)
          {
            --m;
            break;
          }
        if(op[m]==1)
          {
            scanf("%d%d%d",&X1[m],&Y1[m],&Vs[m]);
            ++n;
          }
        else
          scanf("%d%d%d%d",&X1[m],&Y1[m],&X2[m],&Y2[m]);
      }
    int blo=(int)sqrt((double)n*log2((double)n));
    n=0;
    for(int i=1;i<=m;++i)
      {
        if(op[i]==1)
          {
            ++n;
            T[n].p[0]=X1[i];
            T[n].p[1]=Y1[i];
            T[n].w=Vs[i];
            T[n].Init();
            if(n>1)
              Insert();
            if(blo==1 || blo==0 || n%blo==0)
              {
                Clear();
                Buildtree();
                root=(1+n>>1);
              }
          }
        else
          {
            qp[0][0]=X1[i];
            qp[0][1]=Y1[i];
            qp[1][0]=X2[i];
            qp[1][1]=Y2[i];
            ans=0;
            if(n)
              Query();
            printf("%d\n",ans+(qp[1][1]-qp[1][0]+1)*(qp[0][1]-qp[0][0]+1)*Begin);
          }
      }
    return 0;
}
时间: 2024-10-25 03:40:08

【kd-tree】bzoj1176 [Balkan2007]Mokia的相关文章

【BZOJ3669】[Noi2014]魔法森林【Link-Cut Tree】【最小生成树】

[题目链接] 一开始写了个二分a+最短路b,骗了65分,然后改成二分b+最短路a,骗了70分..发现二分是不对的之后,给答案取min,骗到了90分.出题人太不负责任了. 正解是枚举a,用LCT维护b的最小生成树. /* Telekinetic Forest Guard */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 500

[BZOJ1176][Balkan2007]Mokia cdq+树状数组

1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 3134  Solved: 1395[Submit][Status][Discuss] Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

【BZOJ】1176: [Balkan2007]Mokia(cdq分治)

http://www.lydsy.com/JudgeOnline/problem.php?id=1176 在写这题的时候思维非常逗啊........2333................... 最后不得不去看别人的代码.. 噗,,我怎么没想到二维前缀和.................... orz zyf 那么对于一个矩形,我们拆成四个点,那么就可以和add操作一起cdq分治! orz cdq分治的话很好想的: 定义$solve(l, r)$表示用l~mid来更新mid+1~r. 考虑如何$

bzoj2581 [USACO 2012 Jan Gold] Cow Run【And-Or Tree】

传送门1:http://www.usaco.org/index.php?page=viewproblem2&cpid=110 传送门2:http://www.lydsy.com/JudgeOnline/problem.php?id=2581 这题我一看就知道自己不会了,只想了个O(2^n * 2 ^ n)即O(2 ^ 2n)的大暴力,也懒得打了,果断看solution. 看了之后惊呆了,看到了一种从未见过,闻所未闻的树叫做And-Or Tree,百度了一下,并没有官方中文翻译,姑且叫他"

【Same Tree】cpp

题目: Given two binary trees, write a function to check if they are equal or not. Two binary trees are considered equal if they are structurally identical and the nodes have the same value. 代码: /** * Definition for a binary tree node. * struct TreeNode

【poj2486】【Apple Tree】【树形dp】

Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7893 Accepted: 2642 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of

【Symmetric Tree】cpp

题目: Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For example, this binary tree is symmetric: 1 / 2 2 / \ / 3 4 4 3 But the following is not: 1 / 2 2 \ 3 3 Note:Bonus points if you could solve it both

BZOJ1176 [Balkan2007]Mokia

就是整体二分啦... 然后我们把一个矩形的询问拆成四个,按x排序按y加入bit中就可以O(n * logn^2)做出来啦~ 1 /************************************************************** 2 Problem: 1176 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:4620 ms 7 Memory:25808 kb 8 *********************

【hdu2815-Mod Tree】高次同余方程-拓展BadyStepGaintStep

http://acm.hdu.edu.cn/showproblem.php?pid=2815 题意:裸题... 题解:又有一个坑,就是N>=P的时候输出无解. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<algorithm> 7 using namespac