BZOJ1176: [Balkan2007]Mokia CDQ分治

最近很不对啊=w= 写程序全是bug啊

ans数组开小了竟然一直不知道,小数据没问题大数据拍不过,交上去RE

蛋疼半天

这个主要把每次询问拆成3个询问。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
#define dout printf
using namespace std;

const int Maxw=2000000+10,Maxm=160000+10,Maxq=10000+10;
typedef long long ll;
int S,W,tot,C[Maxw],ans[Maxm+Maxq*4];

void Add(int x,const int&d){
    for(;0<x&&x<=W;x+=x&-x)C[x]+=d;
}
int Query(int x){
    int ret=0;
    for(;0<x&&x<=W;x-=x&-x)ret+=C[x];
    return ret;
}

const int Hmod=1e5+7;
struct node{
    bool tp;//0 for modify and 1 for query
    int x,y,ans,id;
    node(int x,int y,int tp,int ans,int id):tp(tp),x(x),y(y),ans(ans),id(id){}
    node(){ans=0;}
}da[Maxq*4+Maxm],q[Maxq*4+Maxm];

struct prob{
    int s1,s2,s3,s4,t;
    void init(int x1,int y1,int x2,int y2){
        ++tot,da[s1=tot]=node(x2,y2,1,0,tot);
        if(x1==1||y1==1)s2=0;
        else ++tot,da[s2=tot]=node(x1-1,y1-1,1,0,tot);
        if(x1==1)s3=0;
        else ++tot,da[s3=tot]=node(x1-1,y2,1,0,tot);
        if(y1==1)s4=0;
        else ++tot,da[s4=tot]=node(x2,y1-1,1,0,tot);
        t=(x2-x1+1)*(y2-y1+1);
    }
    int calc(){
        return ans[s1]+ans[s2]-(ans[s3]+ans[s4])+t*S;
    }
}pr[Maxq];int totpr=0;

inline bool cmp(const node&a,const node&b){
    if(a.x!=b.x)return a.x<b.x;
    return a.y<b.y;
}
void init(){
    scanf("%d%d",&S,&W);
    for(int x1,y1,x2,y2,d,opt;~scanf("%d",&opt)&&opt!=3;){
        if(opt==1)scanf("%d%d%d",&x1,&y1,&d),++tot,da[tot]=node(x1,y1,0,d,tot);
        else scanf("%d%d%d%d",&x1,&y1,&x2,&y2),pr[++totpr].init(x1,y1,x2,y2);
    }
}

void CDQ(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    CDQ(l,mid);
    CDQ(mid+1,r);
    int i=l;
    for(int j=mid+1;j<=r;j++){
        for(;i<=mid&&da[i].x<=da[j].x;i++)if(!da[i].tp)Add(da[i].y,da[i].ans);
        if(da[j].tp)da[j].ans+=Query(da[j].y);
    }
    for(i--;i>=l;i--)if(!da[i].tp)Add(da[i].y,-da[i].ans);
    merge(da+l,da+mid+1,da+mid+1,da+r+1,q,cmp);
    memcpy(da+l,q,sizeof(da[0])*(r-l+1));
}
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);

    init();
    CDQ(1,tot);
    for(int i=1;i<=tot;i++)ans[da[i].id]=da[i].ans;
    for(int i=1;i<=totpr;i++)printf("%d\n",pr[i].calc());

    return 0;
}

时间: 2024-10-30 21:42:30

BZOJ1176: [Balkan2007]Mokia CDQ分治的相关文章

[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分治

题目大意: 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. POJ1195的加强版 没记错的话上午这题还没有中文题目描述的说0.0 好迅速 首先这题看到W就知道二维树状数组挂了 看到M就发现离散化了也搞不了 0.0 这题似乎是CDQ分治被发现之后第二个解决的题目...不过只有会员才知道的世界,今天反应过来刷刷... 修改和询问放在一起分治,一个询问拆分成4个,树状数组处

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组

Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下三种输入之一(不包含引号): "1 x y a" "2 x1 y1 x2 y2" "3" 输入1:你需要把(x,y)(第x行第y列)的格子权值增加a 输入

BZOJ 1176 Balkan 2007 Mokia CDQ分治

题目大意:有一些操作,给一个坐标代表的点加上一个数,和求出一个矩形中的所有数的和. 思路:一眼题,二位树状数组水过. ... .. . 哪里不对?W<=2000000.逗我?这n^2能开下? 这个时候CDQ神牛又来帮助我们了. 这个题应该算是CDQ分治的模板题了吧,简单分析一下,其实不难. 写这个题之前建议写一下BZOJ 1935 SHOI 2007 Tree 园丁的烦恼 树状数组这个题,是本题的简化版. 按照正常的解法,我们应该建立一个二位的数据结构,然后分别维护两维的信息.如果用动态开点的线

bzoj千题计划144:bzoj1176: [Balkan2007]Mokia

http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ分治 #include<cstdio> #include<iostream> #include<algorithm> #define lowbit(x) x&-x using namespace std; #define N 160001 #define M 10001 typedef long long LL; int w; LL c[2000001

cdq分治入门--BZOJ1176: [Balkan2007]Mokia

对w*w,w<=2000000的矩形,一开始全是0(或一开始全是s),n<=170000个操作,每次操作:矩阵内某点加上一个数,查某一个子矩阵的和,保证修改数<=160000,询问数<=10000. 这还是一个比较明显的三维偏序:时间维,以及x和y.由于现在时间维是一个Ti<Tj,而x和y是要查x1<=x<=x2,y1<=y<=y2,查一个范围答案在归并排序直接查不方便,所以一个询问拆4个,就变成普通的三维偏序了. 1 #include<stdi

[bzoj] 1176 Mokia || CDQ分治

原题 给出W×W的矩阵(S没有用,题目有误),给出无限次操作,每次操作的含义为: 输入1:你需要把(x,y)(第x行第y列)的格子权值增加a 输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出 输入3:表示输入结束 因为修改之间相互独立,所以可以用CDQ. 三个维度分别为时间,x轴,y轴. 简单的三维偏序即可. #include<cstdio> #include<algorithm> #define N 100010 #define

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 *********************

【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[