[hdu7062]A Simple Problem
称序列$\{a_{1},a_{2},...,a_{n}\}$的答案为$\min_{0\le i\le n-k}(\max_{i<j\le i+k}a_{j})$(特别的,若$n<k$则为$\infty$)
将序列按$k$分段,每一段长度为$k$(最后一段长度可以小于$k$),那么恰有$\lceil\frac{n}{k}\rceil$段
考虑维护第$i$段和第$i+1$段拼接成的序列的答案,那么如果相邻两段都全在修改或查询区间内,直接再维护一棵线段树即可(支持区间加和区间取$\min$),并对剩下$o(1)$个暴力计算即可(单点修改)
关于如何"暴力计算",做法如下:
问题即选择第$i$段的一个后缀和第$i+1$段的一个前缀(都可以为空),长度和为$k$并最小化两者的最大值
(另外,如果是查询,还会对其长度有一定限制,但并不影响下面的做法)
显然两者随长度的增长单调不下降,因此即需要找到最短的后缀使得其对应的前缀(长度和为$k$)最大值小于后缀最大值(类似地找到最短的后缀),那么答案即这两个位置
简单的做法即二分+线段树做到$o(\log^{2}n)$,但注意到可以对每一段都建一棵线段树,且让两者形态相同(将最后一段长度补至$k$),那么就可以在两棵线段树上一起二分,时间复杂度降为$o(\log n)$
最终,总复杂度为$o(q\log n)$,可以通过
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 3000005
4 #define oo 0x3f3f3f3f
5 #define mid (l+r>>1)
6 int t,n,m,q,p,l,r,x;
7 namespace VAL{
8 int V,Rt,ls[N],rs[N],tag[N],f[N];
9 unordered_map<int,int>rt;
10 void init(){
11 V=Rt=0;
12 rt.clear();
13 }
14 int New(){
15 int k=++V;
16 ls[k]=rs[k]=tag[k]=f[k]=0;
17 return k;
18 }
19 void upd(int &k,int x){
20 if (!k)k=New();
21 tag[k]+=x,f[k]+=x;
22 }
23 void up(int k){
24 f[k]=max(f[ls[k]],f[rs[k]])+tag[k];
25 }
26 void down(int k){
27 if (!tag[k])return;
28 upd(ls[k],tag[k]);
29 upd(rs[k],tag[k]);
30 tag[k]=0;
31 }
32 void update(int &k,int l,int r,int x,int y,int z){
33 if ((l>y)||(x>r))return;
34 if (!k)k=New();
35 if ((x<=l)&&(r<=y)){
36 upd(k,z);
37 return;
38 }
39 update(ls[k],l,mid,x,y,z);
40 update(rs[k],mid+1,r,x,y,z);
41 up(k);
42 }
43 void get_tag(int k,int l,int r,int x){
44 if (!k)return;
45 if (l==r){
46 upd(rt[x],tag[k]),tag[k]=0;
47 return;
48 }
49 down(k);
50 if (x<=mid)get_tag(ls[k],l,mid,x);
51 else get_tag(rs[k],mid+1,r,x);
52 up(k);
53 }
54 int query(int k,int l,int r,int x,int y){
55 if ((l>y)||(x>r))return -oo;
56 if ((!k)||(x<=l)&&(r<=y))return f[k];
57 return max(query(ls[k],l,mid,x,y),query(rs[k],mid+1,r,x,y))+tag[k];
58 }
59 int find(int k1,int k2,int l,int r,int x,int y){
60 if (l==r)return l;
61 down(k1),down(k2);
62 int xx=max(x,f[rs[k1]]),yy=max(y,f[ls[k2]]);
63 if (xx>=yy)return find(rs[k1],rs[k2],mid+1,r,x,yy);
64 return find(ls[k1],ls[k2],l,mid,xx,y);
65 }
66 void update(int pos,int l,int r,int x){
67 if (l<=r){
68 if (!pos)update(Rt,1,n/m,l,r,x);
69 else update(rt[pos],1,m,l,r,x);
70 }
71 }
72 int query(int pos,int l,int r){
73 if (l>r)return oo;
74 get_tag(Rt,1,n/m,pos),get_tag(Rt,1,n/m,pos+1);
75 l=min(max(find(rt[pos],rt[pos+1],1,m,-oo,-oo),l),r);
76 int ans=max(query(rt[pos],1,m,l,m),query(rt[pos+1],1,m,1,l-1));
77 if (l<r)ans=min(ans,max(query(rt[pos],1,m,l+1,m),query(rt[pos+1],1,m,1,l)));
78 return ans;
79 }
80 };
81 namespace ANS{
82 int V,rt,ls[N],rs[N],tag[N],f[N];
83 void init(){
84 V=rt=0;
85 }
86 int New(){
87 int k=++V;
88 ls[k]=rs[k]=tag[k]=f[k]=0;
89 return k;
90 }
91 void upd(int &k,int x){
92 if (!k)k=New();
93 tag[k]+=x,f[k]+=x;
94 }
95 void up(int k){
96 f[k]=min(f[ls[k]],f[rs[k]])+tag[k];
97 }
98 void down(int k){
99 if (!tag[k])return;
100 upd(ls[k],tag[k]);
101 upd(rs[k],tag[k]);
102 tag[k]=0;
103 }
104 void update(int &k,int l,int r,int x,int y){
105 if (!k)k=New();
106 if (l==r){
107 tag[k]=0,f[k]=y;
108 return;
109 }
110 down(k);
111 if (x<=mid)update(ls[k],l,mid,x,y);
112 else update(rs[k],mid+1,r,x,y);
113 up(k);
114 }
115 void update(int &k,int l,int r,int x,int y,int z){
116 if ((l>y)||(x>r))return;
117 if (!k)k=New();
118 if ((x<=l)&&(r<=y)){
119 upd(k,z);
120 return;
121 }
122 update(ls[k],l,mid,x,y,z);
123 update(rs[k],mid+1,r,x,y,z);
124 up(k);
125 }
126 int query(int k,int l,int r,int x,int y){
127 if ((l>y)||(x>r))return oo;
128 if ((!k)||(x<=l)&&(r<=y))return f[k];
129 return min(query(ls[k],l,mid,x,y),query(rs[k],mid+1,r,x,y))+tag[k];
130 }
131 void update(int pos,int x){
132 update(rt,1,n/m,pos,x);
133 }
134 void update(int l,int r,int x){
135 if (l<=r)update(rt,1,n/m,l,r,x);
136 }
137 int query(int l,int r){
138 if (l>r)return oo;
139 return query(rt,1,n/m,l,r);
140 }
141 };
142 int bl(int k){
143 return (k+m-1)/m;
144 }
145 int st(int k){
146 return (k-1)*m+1;
147 }
148 int ed(int k){
149 return k*m;
150 }
151 void update(int l,int r,int x){
152 int ll=bl(l),rr=bl(r);
153 if (ll==rr)VAL::update(ll,l-st(ll)+1,r-st(ll)+1,x);
154 else{
155 VAL::update(0,ll+1,rr-1,x);
156 VAL::update(ll,l-st(ll)+1,m,x);
157 VAL::update(rr,1,r-st(rr)+1,x);
158 ANS::update(ll+1,rr-2,x);
159 }
160 if (ll>1)ANS::update(ll-1,VAL::query(ll-1,1,m));
161 if (ll<n/m)ANS::update(ll,VAL::query(ll,1,m));
162 if (ll<rr-1)ANS::update(rr-1,VAL::query(rr-1,1,m));
163 if ((ll<rr)&&(rr<n/m))ANS::update(rr,VAL::query(rr,1,m));
164 }
165 int query(int l,int r){
166 int ll=bl(l),rr=bl(r+1),ans=ANS::query(ll+1,rr-2);
167 if (ll+1==rr)return min(ans,VAL::query(ll,l-st(ll)+1,r-st(rr)+2));
168 return min(ans,min(VAL::query(ll,l-st(ll)+1,m),VAL::query(rr-1,1,r-st(rr)+2)));
169 }
170 int main(){
171 scanf("%d",&t);
172 while (t--){
173 scanf("%d%d%d",&n,&m,&q);
174 n=(n+m-1)/m*m;
175 VAL::init(),ANS::init();
176 for(int i=1;i<=q;i++){
177 scanf("%d%d%d",&p,&l,&r);
178 if (p==1){
179 scanf("%d",&x);
180 update(l,r,x);
181 }
182 if (p==2)printf("%d\n",query(l,r));
183 }
184 }
185 return 0;
186 }
[hdu7062]A Simple Problem的更多相关文章
- POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)
A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...
- POJ 3468 A Simple Problem with Integers(线段树/区间更新)
题目链接: 传送门 A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Description Yo ...
- poj 3468:A Simple Problem with Integers(线段树,区间修改求和)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 58269 ...
- ACM: A Simple Problem with Integers 解题报告-线段树
A Simple Problem with Integers Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%lld & %l ...
- poj3468 A Simple Problem with Integers (线段树区间最大值)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92127 ...
- POJ3648 A Simple Problem with Integers(线段树之成段更新。入门题)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53169 Acc ...
- BZOJ-3212 Pku3468 A Simple Problem with Integers 裸线段树区间维护查询
3212: Pku3468 A Simple Problem with Integers Time Limit: 1 Sec Memory Limit: 128 MB Submit: 1278 Sol ...
- POJ 3468 A Simple Problem with Integers(线段树区间更新区间查询)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92632 ...
- A Simple Problem with Integers(树状数组HDU4267)
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
随机推荐
- Rafy 框架 - 实体支持只更新部分变更的字段
Rafy 快一两年没有大的更新了.并不是这个框架没人维护了.相反,主要是因为自己的项目.以及公司在使用的项目,都已经比较稳定了,也没有新的功能添加.但是最近因为外面使用了 Rafy 的几个公司,找到我 ...
- 鲲鹏展翅|SphereEx 获华为鲲鹏技术认证
SphereEx Data Middleware 通过了华为鲲鹏技术认证并加入鲲鹏展翅伙伴计划,未来 SphereEx Data Middleware 产品将继续以分布式能力为基础,以数据安全.分布式 ...
- 重修 Tarjan
Tarjan是谁 Tarjan's SCCs(有向图强连通分量)algorithm 给定⼀个有向图 \(G\),若存在 \(rt\in V\),满⾜从 \(rt\) 出发能到达 \(V\) 中的所有的 ...
- python中列表和元组的区别
列表(list)特点: 1.可变类型且有序的,有索引值. 元组特点: 1.不可变类型且有序的,通过下标索引值访问 2.元组里面只有一个元素的时候该元组类型就是这个元素的类型.例如:t=(1) t的类型 ...
- DataX的安装及使用
DataX的安装及使用 目录 DataX的安装及使用 DataX的安装 DataX的使用 stream2stream 编写配置文件stream2stream.json 执行同步任务 执行结果 mysq ...
- 6月6日 Scrum Meeting
日期:2021年6月6日 会议主要内容概述: 删除模板选择页面,画图页面新增模板选择 保存时后端判重 后端要新增数据分享url 主题色->lxd:画图教程->lsp:表格数据分析-> ...
- [技术博客] BeautifulSoup4分析网页
[技术博客] BeautifulSoup4分析网页 使用BeautifulSoup4进行网页文本分析 前言 进行网络爬虫时我们需要从网页源代码中提取自己所需要的信息,分析整理后存入数据库中. 在pyt ...
- Vue3+Typescript+Node.js实现微信端公众号H5支付(JSAPI v3)教程--各种填坑
----微信支付文档,不得不说,挺乱!(吐槽截止) 功能背景 微信公众号中,点击菜单或者扫码,打开公众号中的H5页面,进行支付. 一.技术栈 前端:Vue:3.0.0,typescript:3.9.3 ...
- Noip模拟68 2021.10.4
T1 玩水 成功在考试的时候注释掉正解,换成了暴力,只因为不敢保证正解思路的正确 脑子瓦特了,不知道把暴力打成函数拼在一起,不知道当时咋想的.... 就是你找有没有一个点上面和左面的字符一样, 如果这 ...
- 绘制PCB电路原理图的8种方法
1.选择集成电路,变压器,晶体管等组件,这些组件体积庞大,有许多引脚并在电路中起主要作用,然后从选定的参考引脚中抽取,以减少错误. 2.如果PCB上标有元件编号(如VD870,R330,C466等), ...