前言:水篇文章,感觉是道好题
题意:支持区间加,已经区间查询
m
i
n
(
m
a
x
(
a
i
.
.
.
a
i
+
K
−
1
)
)
(
l
<
=
i
<
=
i
+
K
−
1
<
=
r
)
min(max(a_i...a_{i+K-1}))(l<=i<=i+K-1<=r)
min(max(ai...ai+K−1))(l<=i<=i+K−1<=r)
K固定,
2
⩽
K
⩽
n
⩽
5
∗
1
0
8
,
q
⩽
2
∗
1
0
5
2\leqslant K \leqslant n \leqslant 5*10^8,q\leqslant 2*10^5
2⩽K⩽n⩽5∗108,q⩽2∗105
题解:把原序列分成n/K块,每块长度为K,于是一段长K的就是横跨两块的
考虑维护相邻两段的影响
考虑区间加,对此的影响除了区间加,还有
O
(
1
)
O(1)
O(1)部分的区间重构
解决重构,保证每块的线段树同构即可,于是就没了
时空的复杂度
O
(
q
l
o
g
2
n
)
O(qlog_2n)
O(qlog2n)
一点小bb:考场上写了双log还写挂了(写对了也会T),不会同构的菜鸡博主是屑。
打了四场HDU,RK是15,8,10,6
四场我都是半程不到就歇菜了,都是CY在猛带,感觉我给力一点,可能就会有次rk前三的(最后一场打表unsigned int不加u的博主是屑)
今天打了Luogu,A是FLS带了一手才会的,我是屑
明天就是百度之星复赛了,这状态估计进不了决赛了
后面的路我也不知道该干啥,估计自己不是那么纯粹了
#include<bits/stdc++.h>
using namespace std;
#define cout cerr
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define FR first
#define SE second
typedef long long ll;
typedef pair<int,int> pii;
inline void rd(int &x){
x=0;char ch=getchar();int f=1;
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
int n,K,q,len;//[1,len)
#define Maxn 100010
#define V 15000010
const int inf=1e9+5;
struct Node{
int mx,mn,tg;
int v;
int ls,rs;
Node(){mx=mn=tg=v=ls=rs=0;}
void init(){mx=mn=tg=v=ls=rs=0;}
}tree[V];
map<int,int> mp;int tot;
int rt[Maxn<<1],root,cnt=0;
void newnode(int &k){
k=++cnt;
tree[k].init();
}
void push_up(int k){
int ls=tree[k].ls,rs=tree[k].rs;
tree[k].mx=max(tree[ls].mx,tree[rs].mx);
tree[k].mn=min(tree[ls].mn,tree[rs].mn);
}
void make_tag(int &k,int t){
if(!k)newnode(k);
tree[k].mx+=t;tree[k].mn+=t;tree[k].tg+=t;
}
void push_down(int k){
make_tag(tree[k].ls,tree[k].tg);make_tag(tree[k].rs,tree[k].tg);
tree[k].tg=0;
}
void ADD(int k,int l,int r,int L,int R,int t){
if(l==L&&r==R){
make_tag(k,t);
return;
}
push_down(k);
int mid=(l+r)>>1;
if(R<=mid)ADD(tree[k].ls,l,mid,L,R,t);
else if(mid<L)ADD(tree[k].rs,mid+1,r,L,R,t);
else{
ADD(tree[k].ls,l,mid,L,mid,t);
ADD(tree[k].rs,mid+1,r,mid+1,R,t);
}
push_up(k);
}
void addv(int k,int l,int r,int L,int R,int t){
if(l==L&&r==R){
tree[k].v+=t;
return;
}
push_down(k);
int mid=(l+r)>>1;
if(R<=mid)addv(tree[k].ls,l,mid,L,R,t);
else if(mid<L)addv(tree[k].rs,mid+1,r,L,R,t);
else{
addv(tree[k].ls,l,mid,L,mid,t);
addv(tree[k].rs,mid+1,r,mid+1,R,t);
}
}
void Modify(int k,int l,int r,int p,int t){
if(l==r){
tree[k].mn=tree[k].mx=t;
return;
}
push_down(k);
int mid=(l+r)>>1;
if(p<=mid)Modify(tree[k].ls,l,mid,p,t);
else Modify(tree[k].rs,mid+1,r,p,t);
push_up(k);
}
int query(int k,int l,int r,int p){
if(l==r)return tree[k].v;
int mid=(l+r)>>1;
if(p<=mid)return tree[k].v+query(tree[k].ls,l,mid,p);
else return tree[k].v+query(tree[k].rs,mid+1,r,p);
}
int qmin(int k,int l,int r,int L,int R){
if(l==L&&r==R)return tree[k].mn;
int mid=(l+r)>>1;
if(R<=mid)return qmin(tree[k].ls,l,mid,L,R)+tree[k].tg;
else if(mid<L)return qmin(tree[k].rs,mid+1,r,L,R)+tree[k].tg;
else return min(qmin(tree[k].ls,l,mid,L,mid),qmin(tree[k].rs,mid+1,r,mid+1,R))+tree[k].tg;
}
void calc(int x,int l,int r,int t){
l=max(l,x*K-K+1);r=min(r,x*K);
if(l>r)return;
l-=(x-1)*K;r-=(x-1)*K;
if(!mp[x]){
mp[x]=++tot;
newnode(rt[tot]);
}
ADD(rt[mp[x]],1,K,l,r,t);
}
int gao(int k1,int k2,int l,int r,int L,int R,int v1,int v2){
if(l==r)return v1+tree[k1].mx;
int mid=(l+r)>>1;
v1+=tree[k1].tg;v2+=tree[k2].tg;
if(R<=mid||mid<L){
if(R<=mid)return max(v2+tree[tree[k2].rs].mx,gao(tree[k1].ls,tree[k2].ls,l,mid,L,R,v1,v2));
else return max(v1+tree[tree[k1].ls].mx,gao(tree[k1].rs,tree[k2].rs,mid+1,r,L,R,v1,v2));
}
int s1=v1+tree[tree[k1].ls].mx,s2=v2+tree[tree[k2].rs].mx;
if(s1>s2){
return min(s1,max(s2,gao(tree[k1].ls,tree[k2].ls,l,mid,L,mid,v1,v2)));
}else return min(s2,max(s1,gao(tree[k1].rs,tree[k2].rs,mid+1,r,mid+1,R,v1,v2)));
}
int run(int l,int r,int p){
l=max(l,p*K-K+1);r=min(r,p*K+K);
l=p*K-l+1;r-=p*K;
int v1=query(root,1,len,p+1),v2=query(root,1,len,p),res=inf;
if(max(1,K-l)<=r)res=min(res,gao(rt[mp[p+1]],rt[mp[p]],1,K,max(1,K-l),r,v1,v2));
if(l>=K)res=min(res,v2+tree[rt[mp[p]]].mx);
return res;
}
void calculate(int l,int r){
int tl=(l+K-1)/K,tr=r/K;
int res=min(run(l,r,tl),run(l,r,tr));
if(tl<tr-1)res=min(res,qmin(root,1,len,tl+1,tr-1));
printf("%d\n",res);
}
void Run(int x){
if(x<1||x>=len)return;
Modify(root,1,len,x,run((x-1)*K+1,(x+1)*K,x));
}
void init(){
cnt=0;tot=0;
mp.clear();
newnode(root);
}
int main(){
int T;
rd(T);
while(T--){
rd(n);rd(K);rd(q);
len=n/K;len++;n=(len+1)*K;
init();
int opt,l,r,x;
rep(i,1,q){
rd(opt);rd(l);rd(r);
if(opt==2)calculate(l,r);
else{df
rd(x);
if(tl<tr-1)ADD(root,1,len,tl+1,tr-1,x);
calc(tl,l,r,x);if(tr+1!=tl)calc(tr+1,l,r,x);
if(tl+1<=tr)addv(root,1,len,tl+1,tr,x);
Run(tl);Run(tl-1);Run(tr);Run(tr+1);
}
}
}
return 0;
}