题解 P7602【[THUPC2021] 视频倍增期】
题意
给你一个序列 $a$,两种操作:
- 区间加
- 单点询问满足第 $i$ 个时间刻 $2a_p\ge$ 现在的 $a_p$ 中 $i$ 的最小值。
思路
直接上主席树。
操作时首先将根设为上次的根,修改时可以直接对区间打标记,标记永久化即可;询问时考虑二分时间节点,在相应的根上单点查询是否满足,注意题目说修改的 $x$ 满足 $x\ge1$,则单点单调不降,具有单调性,正确性存在。
时间复杂度 $O(n\log^2n)$,空间复杂度 $O(n\log n)$。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=1e5+10;
int n,m,a[N],rt[N];
struct tree{
int cnt;
struct node{
ll ans;
int ls,rs;
}a[N*80];
inline void update(int &root,int pre,int l,int r,int ql,int qr,int k){
root=++cnt;
a[root]=a[pre];
if(ql<=l&&r<=qr){
a[root].ans+=k;
return ;
}
int mid=l+r>>1;
if(ql<=mid){
update(a[root].ls,a[pre].ls,l,mid,ql,qr,k);
}
if(qr>mid){
update(a[root].rs,a[pre].rs,mid+1,r,ql,qr,k);
}
}
inline ll query(int root,int l,int r,int q){
if(!root) return 0;
if(l==r){
return a[root].ans;
}
int mid=l+r>>1;
if(q<=mid){
return query(a[root].ls,l,mid,q)+a[root].ans;
}else{
return query(a[root].rs,mid+1,r,q)+a[root].ans;
}
}
}t;
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
int opt=read();
switch(opt){
case 0:{
int l=read(),r=read(),w=read();
t.update(rt[i],rt[i-1],1,n,l,r,w);
break;
}
case 1:{
int p=read();
rt[i]=rt[i-1];
ll now=t.query(rt[i],1,n,p);
int l=0,r=i-1;
while(l<r){
int mid=l+r>>1;
if(t.query(rt[mid],1,n,p)*2>=now){
r=mid;
}else{
l=mid+1;
}
}
write(i-l);
putc('\n');
break;
}
}
}
flush();
return 0;
}
再见 qwq~

浙公网安备 33010602011771号