蒟蒻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