BZOJ 2683 简单题 cdq分治+树状数组

题意:链接

**方法:**cdq分治+树状数组

解析:

首先对于这道题,看了范围之后,二维的数据结构是显然不能过的,于是我们可能会考虑把一维排序之后另一位上数据结构什么的,然而cdq分治却能够很好的体现它的作用。

首先,对于每一个询问求和,显然是x在它左边的并且出现时间在它之前的所有的change对他可能会有影响。

我们按照x第一关键字,y第二关键字,操作第三关键字来排序所有的询问,然后在cdq的时候,每次递归处理左半区间,按照x动态的将y这一列的值加到树状数组里,来更新右半边的所有询问,注意这里的树状数组是需要清的,也就是每次cdq都是采用不同的树状数组。

另:这题神坑,数组开小不是RE而是WA

数组范围是要开到200000*4的,因为对于每个1操作,是一个操作,而2操作根据容斥原理,是4个操作。所以复杂度大概是多少呢O(nlog^2(n))cdq+树状数组。n<=800000

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 800010
#define Q q[tot]
using namespace std;
struct node
{
    int opt,x,y,A,no,belong;
}q[N],nq[N];
int n;
int jd,tot,T;
int ans[N];
int c[N];
int lowbit(int x){return x&(-x);}
int getsum(int x){int ret=0;while(x){ret+=c[x],x-=lowbit(x);}return ret;}
void update(int x,int v){while(x<=n){c[x]+=v;x+=lowbit(x);}}
int cmp(node a,node b)
{
    if(a.x==b.x&&a.y==b.y)return a.opt<b.opt;
    if(a.x==b.x)return a.y<b.y;
    return a.x<b.x;
}
void sov(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1,l1=l,l2=mid+1;
    for(int i=l;i<=r;i++)
    {
        if(q[i].no<=mid&&q[i].opt==1)update(q[i].y,q[i].A);
        if(q[i].no>mid&&q[i].opt==2)ans[q[i].belong]+=getsum(q[i].y);
    }
    for(int i=l;i<=r;i++)
    {
        if(q[i].no<=mid&&q[i].opt==1)update(q[i].y,-q[i].A);
    }
    l1=l,l2=mid+1;
    for(int i=l;i<=r;i++){if(q[i].no<=mid)nq[l1++]=q[i];else nq[l2++]=q[i];}
    for(int i=l;i<=r;i++)q[i]=nq[i];
    sov(l,mid),sov(mid+1,r);
}
int main()
{
    scanf("%d",&n);
    while(scanf("%d",&jd)&&jd^3)
    {
        if(jd==1){int x,y,a;scanf("%d%d%d",&x,&y,&a);q[++tot].opt=1,Q.x=x,Q.y=y,Q.A=a,Q.no=tot;}
        else
        {
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            q[++tot].opt=2,Q.x=x1-1,Q.y=y1-1,Q.A=1,Q.no=tot,Q.belong=++T;
            q[++tot].opt=2,Q.x=x1-1,Q.y=y2,Q.A=-1,Q.no=tot,Q.belong=T;
            q[++tot].opt=2,Q.x=x2,Q.y=y1-1,Q.A=-1,Q.no=tot,Q.belong=T;
            q[++tot].opt=2,Q.x=x2,Q.y=y2,Q.A=1,Q.no=tot,Q.belong=T;
        }
    }
    sort(q+1,q+1+tot,cmp);
    sov(1,tot);
    for(int i=1;i<=T;i++)printf("%d\n",ans[i]);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 23:06:35

BZOJ 2683 简单题 cdq分治+树状数组的相关文章

bzoj 2683 简单题 cdq分治

题面 题目传送门 解法 可以离线,那么就是非常简单的cdq分治了 只要把询问拆成4个,然后就变成了一个三维偏序问题 时间复杂度:\(O(q\ log^2\ n)\) 代码 #include <bits/stdc++.h> #define int long long #define N 1000010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y

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 2683 简单题 ——CDQ分治

简单题 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 2000005 int sum[maxn]; void a

BZOJ2683: 简单题(CDQ分治 + 树状数组)

BZOJ2683: 简单题(CDQ分治 + 树状数组) 题意: 你有一个\(N*N\)的棋盘,每个格子内有一个整数,初始时的时候全部为\(0\),现在需要维护两种操作: 命令 参数限制 内容 \(1\ x\ y\ A\) \(1\le x,y \le N\),A是正整数 将格子\(x,y\)里的数字加上\(A\) \(2\ x1\ y1\ x2\ y2\) \(1\le x1\le x2\le N,1\le y1\le y2\le N\) 输出\(x1\ y1\ x2\ y2\)这个矩形内的数字

HDU 5618:Jam&#39;s problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:-- 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 #d

XJOI NOIP2015模拟赛Day1 T2 ctps bitset优化 或 排序+cdq分治+树状数组+平衡树

题意: 4维空间中有1个点集A,|A|=n,用(a,b,c,d)表示每个点. 共有m个询问,每次询问输入一个点(a,b,c,d),求最大的S,其中S={p|p∈A且ap<=a,bp<=b,cp<=c,dp<=d},输出|S| 输入格式: 第一行n 接下来n行有n个4维点对 第n+2行有一个数m 再接下来m行每行有一个四维点对,表示每个询问 输出格式: 对于每个询问输出一个数 **方法:**bitset优化 或 排序+cdq分治+树状数组+平衡树 解析: 神题,考场不会,暴力骗40,

【BZOJ4553】[Tjoi2016&amp;Heoi2016]序列 cdq分治+树状数组

[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可.注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1

[cdq分治][树状数组] Bzoj P3262 陌上花开

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb. 显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N

BZOJ 3262: 陌上花开 cdq分治 树状数组

https://www.lydsy.com/JudgeOnline/problem.php?id=3262 cdq分治板子题,一维排序,一维分治(cdq里的队列),一维数据结构(树状数组). 学dp优化前来复习--以前好像写过这道题但是没写博客啊--在校oj上写的题都没怎么写博客,追悔莫及 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #