51Nod 算法马拉松12 Rikka with sequences
当时做比赛的时候听说过这类用KD_Tree维护的数据结构题
然后知道是KD_Tree,然而并不知道怎么写QAQ
比赛完了之后%了一发代码
其基本思路是这样的:
1、首先我们把询问[L,R]看成二维平面上的点,那么对于任意修改[p,p]
当且仅当p>=L&&p<=R时会对答案有影响
对应到二维平面就是KD_Tree维护矩形区域和的经典操作啦
2、那么我们考虑对历史最小值的询问
先把修改转换为增量修改
我们可以在KD_Tree上维护两个标记
第一个是当前的ADD
第二个是历史所有的Minadd
这样在更改一下push_down函数就可以完成了
QAQ 高仿的代码,真是羞耻 QAQ
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std; typedef long long LL;
const int maxn=100010;
const int oo=0x7fffffff;
int n,m,D,cnt,rt;
int A[maxn],type[maxn],L[maxn],R[maxn];
LL Bit[maxn],ans[maxn]; void add(int x,int v){for(int i=x;i<=n;i+=(i&(-i)))Bit[i]+=v;}
LL ask(int x){
LL sum=0;
for(int i=x;i>=1;i-=(i&(-i)))sum+=Bit[i];
return sum;
}
int tot=0;
struct Node{
int d[2],mn[2],mx[2];
int L,R,id;
LL sum,add,ans,Minadd;
bool operator <(const Node &A){return d[D]<A.d[D];}
}t[maxn],tmp[maxn];
void up(int o){
for(int i=0;i<2;++i){
t[o].mn[i]=min(t[o].d[i],min(t[t[o].L].mn[i],t[t[o].R].mn[i]));
t[o].mx[i]=max(t[o].d[i],max(t[t[o].L].mx[i],t[t[o].R].mx[i]));
}return;
}
void push_1(int o,LL v){
if(!o)return;
t[o].ans=min(t[o].ans,t[o].sum+v);
t[o].Minadd=min(t[o].Minadd,t[o].add+v);
}
void push_2(int o,LL v){
if(!o)return;
t[o].sum+=v;t[o].add+=v;
t[o].ans=min(t[o].ans,t[o].sum);
t[o].Minadd=min(t[o].Minadd,t[o].add);
}
void push_down(int o){
if(t[o].Minadd){
push_1(t[o].L,t[o].Minadd);
push_1(t[o].R,t[o].Minadd);
t[o].Minadd=0;
}
if(t[o].add){
push_2(t[o].L,t[o].add);
push_2(t[o].R,t[o].add);
t[o].add=0;
}
}
void modify(int o,int p,int val){
if(!o)return;
push_down(o);
if(t[o].mx[0]<=p&&t[o].mn[1]>=p){push_2(o,1LL*val);return;}
if(t[o].d[0]<=p&&t[o].d[1]>=p)t[o].sum+=val,t[o].ans=min(t[o].ans,t[o].sum);
if(t[t[o].L].mn[0]<=p&&t[t[o].L].mx[1]>=p)modify(t[o].L,p,val);
if(t[t[o].R].mn[0]<=p&&t[t[o].R].mx[1]>=p)modify(t[o].R,p,val);
}
void insert(int &o,int x,int y,int id,int c){
if(!o){
o=++tot;t[o].d[0]=x;t[o].d[1]=y;
t[o].id=id;t[o].sum=t[o].ans=ask(y)-ask(x-1);
up(o);
return;
}
push_down(o);
if(c==0){
if(x<=t[o].d[0])insert(t[o].L,x,y,id,c^1);
else insert(t[o].R,x,y,id,c^1);
}else{
if(y<=t[o].d[1])insert(t[o].L,x,y,id,c^1);
else insert(t[o].R,x,y,id,c^1);
}up(o);
}
void DFS(int o){
if(!o)return;
push_down(o);
DFS(t[o].L);
tmp[++cnt]=t[o];
ans[t[o].id]=t[o].ans;
DFS(t[o].R);
}
void build(int &o,int L,int R,int c){
o=0;if(L>R)return;
int mid=(L+R)>>1;D=c;o=mid;
nth_element(tmp+L,tmp+mid,tmp+R+1);
t[o]=tmp[mid];
build(t[o].L,L,mid-1,c^1);
build(t[o].R,mid+1,R,c^1);
up(o);
}
int main(){
rt=0;
t[0].mn[0]=t[0].mn[1]=oo;
t[0].mx[0]=t[0].mx[1]=-oo;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&A[i]),add(i,A[i]);
for(int i=1;i<=m;++i){
scanf("%d%d%d",&type[i],&L[i],&R[i]);
if(type[i]==1){
add(L[i],R[i]-A[L[i]]);
R[i]=R[i]-A[L[i]];
A[L[i]]+=R[i];
}
}
int blo=2000;
for(int i=m;i>=1;--i){
if(type[i]==1)modify(rt,L[i],-R[i]),add(L[i],-R[i]);
else insert(rt,L[i],R[i],i,0);
if(i%blo==0){
cnt=0;DFS(rt);rt=0;
build(rt,1,cnt,0);
}
}
cnt=0;DFS(rt);
for(int i=1;i<=m;++i){
if(type[i]==2)printf("%lld\n",ans[i]);
}return 0; }
51Nod 算法马拉松12 Rikka with sequences的更多相关文章
- 51nod算法马拉松12
A 第K大区间 不妨考虑二分答案x,则问题转化成计算有多少个区间满足众数出现的次数>=x. 那么这个问题我们使用滑动窗口,枚举右端点,则左端点肯定单调递增,然后维护一个简单的数组就能资瓷添加元素 ...
- 51NOD 算法马拉松12
OTZ做出题目的神犇..断断续续改完了在这里存一下思路吧 A题:第K大区间题意:定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. 分析:二分答案mid,任务 ...
- 51Nod 算法马拉松12 移数博弈
点进去发现并不是博弈QAQ 一开始考虑单调队列什么乱七八糟的发现根本做不出来 (没错我一直在想枚举最大值求次大值QAQ 不妨换个思路: 我们考虑枚举次大值求最大值 设当前为now, 设now之前第一个 ...
- 51NOD 算法马拉松8
题目戳这里:51NOD算法马拉松8 某天晚上kpm在玩OSU!之余让我看一下B题...然后我就被坑进了51Nod... A.还是01串 水题..怎么乱写应该都可以.记个前缀和然后枚举就行了.时间复杂度 ...
- 51nod 算法马拉松 34 Problem D 区间求和2 (FFT加速卷积)
题目链接 51nod 算法马拉松 34 Problem D 在这个题中$2$这个质数比较特殊,所以我们先特判$2$的情况,然后仅考虑大于等于$3$的奇数即可. 首先考虑任意一个点对$(i, j)$ ...
- 随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3
先说说前面的SPOJ-RNG吧,题意就是给n个数,x1,x2,...,xn 每次可以生成[-x1,x1]范围的浮点数,把n次这种操作生成的数之和加起来,为s,求s在[A,B]内的概率 连续形的概率 假 ...
- 51Nod 算法马拉松21(迎新年)
这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =). 讲讲比赛经过吧. 8:00准时发题,拿到之后第一时间开始读. A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过 ...
- 51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛
OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就 ...
- 51Nod 算法马拉松23 开黑记
惨啊……虽然开了半天黑,但是还是被dalao们踩了…… 第二次开黑,还是被卡在rank20了,我好菜啊……= = 写一写比赛经过吧…… 看到题之后习惯性都打开,A~D看上去似乎并没有什么思路,F应该是 ...
随机推荐
- 【Qt】Qt Assistant介绍【转】
简介 Qt Assistant也就是我们常说的Qt助手,是一款用于呈现在线文档的工具. 简介 一分钟学会使用 Qt参考文档 Qt Assistant详解 命令行选项 工具窗口 文档窗口 工具栏 菜单 ...
- jQuery对Select操作大集合
介绍了jQuery对Select的操作进行了详细的汇总. 1.jQuery添加/删除Select的Option项: 2.$("#select_id").append("& ...
- 重拾C,一天一点点_6
break与continuecontinue只能用于循环语句goto最常见的用法是终止程序在某些深度嵌套的结构中的处理过程,例如一次跳出两层或多层循环.break只能从最内层循环退出到上一级的循环. ...
- 批量修改文件后缀(Python)
近期下载了很多各种教程, 但是不幸的是后缀名都是 ".mp4", 而本人喜欢 ".rmvb" 后缀,由于有轻微洁癖, 受不了后面的 ".mp4&quo ...
- oracle-linux下挂载"移动硬盘" NTFS类型
环境: ORACLE-LINUX 5.7 全新移动硬盘(未使用过) 移动硬盘空间3T 在默认情况下,Linux系统不支持NTFS分区挂载 1.服务器: A服务器和B服务器为一套ORACLE-RAC,移 ...
- Windows 7 搭建 nodejs、npm、express 环境
准备工作: 下载nodejs (exe format)(http://nodejs.org/) 下载npm(zip format)(http://nodejs.org/dist/npm/) 开始安装 ...
- C++中的虚函数(类的向上转换,和向下转换)
1.C++中的封装时为了代码的模块化,继承是为了代码的重用,而多态则是为了接口的重用. 2.C++中的多态是用虚函数来实现的. 3.子类对象向父类指针的转换(向上转换)是安全的,隐式的,而父类对象向子 ...
- Http之Get/Post请求区别
Http之Get/Post请求区别 1.HTTP请求格式: <request line> <headers> <blank line> [<request-b ...
- CSS function--功能样式
功能样式,从常用样式方法中抽离,按需使用,使用前请先阅读 CSS规范 中相关条列. /* function */ .f-cb:after,.f-cbli li:after{display:block; ...
- [设计模式] 12 代理模式 proxy
在GOF的<设计模式:可复用面向对象软件的基础>一书中对代理模式是这样说的:为其他对象提供一种代理以控制对这个对象的访问.结合上面的游戏代理的例子和下面的图,我们来进行分析一下.以前你是这 ...