蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列
题目描述
DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知
道N次操作后数列中所有元素的和。他还要玩其他游戏,所以这个问题留给你解决。
标签:enter www. efi continue end pre php space mem
动态开点线段树与下标的传递,我们知道线段树的复杂度是2*n*longn,因为下标范围太大,所以我们要动态开点
所以对于n次询问我们可证明最多会新建2*n*logn个点 最后dfs一下求出总和即可
#include <bits/stdc++.h>
#define ll long long
#define inf 1e9
using namespace std;
inline int read(){
int x=0;int f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
const int MAXN=4e4+10;
int ls[MAXN*40],rs[MAXN*40],v[MAXN*40],t,tot,n,rt;
ll ans=0;
inline void insert(int &k,int l,int r,int x,int y){
if(!k){
k=++tot;
}
if(l==x&&r==y){
v[k]=max(v[k],t);return;
}
int mid=(l+r)>>1;
if(x>mid) insert(rs[k],mid+1,r,x,y);
else if(y<=mid) insert(ls[k],l,mid,x,y);
else insert(ls[k],l,mid,x,mid),insert(rs[k],mid+1,r,mid+1,y);
}
inline void query(int k,int l,int r,int x){
if(!k) return;
int mid=(l+r)>>1;
v[k]=max(v[k],x);
if(ls[k]) query(ls[k],l,mid,v[k]);
else ans+=1LL*(mid-l+1)*v[k];
if(rs[k]) query(rs[k],mid+1,r,v[k]);
else ans+=1LL*(r-mid)*v[k];
}
int main(){
n=read();
for(int i=1;i<=n;i++){
int x=read();int y=read();t=read();
if(x==y) continue;
insert(rt,1,inf,x,y-1);
}
query(rt,1,inf,0);
cout<<ans<<endl;
return 0;
}
标签:enter www. efi continue end pre php space mem
原文地址:https://www.cnblogs.com/something-for-nothing/p/9058336.html