这题虽然是个树状数组,但是也可以用cdq分治做啊~~,这个就是一个浅显的二维偏序的应用?

cdq分治和普通的分治有什么区别?

举个栗子:有4个小朋友,你请他们吃饭,假如你分治搞,就会分成很多子问题——1~1号小朋友有多少个来,2~2号小朋友有多少个来,然后程序就会回溯,你就知道1~2号小朋友有多少个来,最后你就知道1~4号小朋友有多少个来了。

而cdq分治呢?同样是4个小朋友,但是要照顾小朋友的心情,第i号小朋友的开心程度是1~i-1号小朋友有多少个来,你想知道小朋友们的心情,有可能心情不好就不来了,那先往左右搜,然后要把心情的影响加上。可能这个栗子不是很贴切,但是我想说的就是cdq分治中,前面的结果会影响后面的,而且,这个算法做题只能离线。

那么,我是拿了这题水题来理解。

俩操作,一个单点修改,一个询问区间和。

那么我们还是照样按前缀和的做法,把询问分成求1~l-1和1~r。

那么离线做,按照输入的顺序放进结构体,这个时候你一定发现了,对于一个询问,对它有影响的修改,就是在它前面操作的,并且修改位置也在它询问位置前面的。那么,实际上这个结构体已经是按照操作的顺序排好了,那么要解决的就是位置的问题。具体的做法,就是按照它的位置,做一次归并排序。

具体怎么做呢,首先先把区间分成l~mid和mid+1~r,当前我们要维护的,就是mid+1~r的全部询问,要先让两边都递归下去,令l~mid的询问解决,以及mid+1~r里的修改施加影响。

那么在归并的过程中,记录一个sum,表示左边已经l~当前归并到的位置的修改值的和,然后当遇到右边的询问,就将影响释放下去,一直这样做下去,当按x排好序了,对于mid+1~r中的询问,l~r的全部影响都已经解决,最后回溯接受更前面的影响,或者去影响后面的其他询问(你这样归排岂不是把一开始操作的顺序打乱了!?不用担心,l~mid的输入顺序每一个都是比mid+1~r大的,l~mid的顺序改变并不会影响后面的修改)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL; int n,m;
struct node
{
int x,tp;LL v;
//tp=1表示这个是修改操作,x表示修改哪个位置,v表示要加上的值
//tp=2,3表示这个是问1~x的前缀和,v表示这个影响第几个答案
}a[],t[];int len=;
void ins(int x,int tp,int v)
{
len++;
a[len].x=x;a[len].tp=tp;a[len].v=v;
}
LL ans[];int ansl=;//答案数组
bool check(node n1,node n2)
{
if(n1.x<n2.x||(n1.x==n2.x&&n1.tp<n2.tp))return true;
return false;
}
void cdq(int l,int r)
{
if(l==r)return ;
int mid=(l+r)/;
cdq(l,mid);cdq(mid+,r); LL sum=;//sum表示l~t[p].x的修改的和
int i=l,j=mid+,p=l;
while(i<=mid&&j<=r)
{
if(check(a[i],a[j])==true)//只统计左边区间内的修改值,因为右边的修改值已经在递归里影响过了
{
if(a[i].tp==)sum+=a[i].v;
t[p++]=a[i++];
}
else//将左边的影响影响右边
{
if(a[j].tp==)ans[a[j].v]-=sum;
else if(a[j].tp==)ans[a[j].v]+=sum;
t[p++]=a[j++];
}
}
while(i<=mid)t[p++]=a[i++];
while(j<=r)
{
if(a[j].tp==)ans[a[j].v]-=sum;
else if(a[j].tp==)ans[a[j].v]+=sum;
t[p++]=a[j++];
} for(int i=l;i<=r;i++)a[i]=t[i];
} char ss[];
int main()
{
int x,l,r;LL v;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%s",ss+);
if(ss[]=='C')
{
scanf("%d%lld",&x,&v);
ins(x,,v);
}
else//利用前缀和的思想,把查询操作分为两部分
{
scanf("%d%d",&l,&r);
ansl++;ins(l-,,ansl);ins(r,,ansl);
}
}
cdq(,len);
for(int i=;i<=ansl;i++)printf("%lld\n",ans[i]);
return ;
}

caioj1097: [视频]树状数组1(快速求和计算) cdq分治入门的更多相关文章

  1. poj 1195:Mobile phones(二维树状数组,矩阵求和)

    Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14489   Accepted: 6735 De ...

  2. HRBUST 1161 树状数组区间更新求和

    Leyni Time Limit: 3000 MS Memory Limit: 65536 K Total Submit: 267(64 users) Total Accepted: 82(57 us ...

  3. P3374 【模板】树状数组 1

    树状数组模板题,用cdq分治做 cdq分治: 分:把l到r分成两个区间操作 治:对每个分出来的区间进行操作 但是cdq分治和一般分治不同的是,一般的分治左右两个区间互不干扰,但是cdq分治处理的是区间 ...

  4. 【bzoj3262】陌上花开 CDQ分治+树状数组

    题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...

  5. 【牛客小白月赛6】F 发电 - 树状数组&快速幂&逆元

    题目地址:https://www.nowcoder.com/acm/contest/136/F 树状数组.快速幂.逆元的模板运用: #include<iostream> #include& ...

  6. HH的项链题解(离线思想+链表+树状数组)

    本人第一篇博客重磅推出!!! 希望各位朋友以后多多捧场也多给写意见(我个人喜欢把题解写得啰嗦一点,因为这样方便理解,各位巨佬勿喷) 来讲一道提高+/省选-的骚题:HH的项链(这个HH你理解成皇后呵呵哈 ...

  7. 树状数组求第k小的元素

    int find_kth(int k) { int ans = 0,cnt = 0; for (int i = 20;i >= 0;i--) //这里的20适当的取值,与MAX_VAL有关,一般 ...

  8. POJ 1990 MooFest(树状数组)

                                                                        MooFest Time Limit: 1000MS   Mem ...

  9. HDU 2689Sort it 树状数组 逆序对

    Sort it Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

随机推荐

  1. mysql 常用命令(二)

    1.创建数据库,并制定默认的字符集是utf8. CREATE DATABASE IF NOT EXISTS yourdbname DEFAULT CHARSET utf8 COLLATE utf8_g ...

  2. iRule Event Order - HTTPv12

  3. iOS第三方地图-百度地图常用功能使用(POI搜索,地理正反编码,定位,添加标注)

    百度地图官网: http://developer.baidu.com/map/index.php?title=iossdk 百度地图集成 1.引入相关包

  4. OC温习一:基本数据类型

    类型限定修饰词 除了上图中基本数据类型之外, 还有一些类型限定修饰词: short短型:修饰 int  double: long长型:修饰 int double: signed 有符号型:修饰int ...

  5. P1918 保龄球 洛谷

    https://www.luogu.org/problem/show?pid=1918 题目描述 DL 算缘分算得很烦闷,所以常常到体育馆去打保龄球解闷.因为他保龄球已经打了几十年了,所以技术上不成问 ...

  6. SharePoint中取得ACL和组中用户数量

     SharePoint中取得ACL和组中用户数量 1. 取得ACL的数量: select COUNT(ra.PrincipalId) as [Count],p.ScopeUrl from [WSS_C ...

  7. 怎样解读Caffe源代码

    怎样解读Caffe源代码 导读 Caffe是如今非常流行的深度学习库,能够提供高效的深度学习训练.该库是用C++编写.能够使用CUDA调用GPU进行加速.可是caffe内置的工具不一定能够满足用户的全 ...

  8. Linux 快照

    10个方法助你轻松完成Linux系统恢复 提交 我的留言 加载中 已留言 这也就是为什么系统恢复功能会让人感觉如此神奇.你可以很快地重新回到工作中去,就像什么事情都没有发生一样,也不用去管造成系统故障 ...

  9. [Javascript] Understanding the .constructor property on JavaScript Objects

    Constructor functions hold an interesting purpose in JavaScript. Unlike in classical languages, they ...

  10. C#如何引用定义好的dll文件

    1 添加引用,找到dll文件   2 引用类的名称空间,生成类的实例,调用类的方法,测试OK.