您的位置:首页 > 其它

【bzoj4636】【蒟蒻的数列】【线段树】

2016-07-08 14:49 549 查看

Description

蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列
题目描述
DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知
道N次操作后数列中所有元素的和。他还要玩其他游戏,所以这个问题留给你解决。

Input

第一行一个整数N,然后有N行,每行三个正整数a、b、k。
N<=40000 , a、b、k<=10^9

Output

一个数,数列中所有元素的和

Sample Input

4

2 5 1

9 10 4

6 8 2

4 6 3

Sample Output

16

题解: 直接在线段树上打标记,最后dfs一遍整棵线段树即可.

因为区间长度比较大,所以需要动态开点.

注意一些没有建立的节点也是有贡献的,要把这些加进去.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 40010
#define inf 1000000000
using namespace std;
int n,a,b,k,cnt,root,ls[N*40],rs[N*40],v[N*40];
long long ans;
int read(){
int x(0);char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void insert(int &k,int l,int r,int ll,int rr,int x){
if (!k) k=++cnt;
int mid=(l+r)>>1;
if (l==ll&&r==rr){
v[k]=max(v[k],x);
//cout<<l<<' '<<r<<' '<<v[k]<<endl;
return;
}
if (rr<=mid) insert(ls[k],l,mid,ll,rr,x);
else if (mid<ll) insert(rs[k],mid+1,r,ll,rr,x);
else{
insert(ls[k],l,mid,ll,mid,x);
insert(rs[k],mid+1,r,mid+1,rr,x);
}
}
void query(int k,int l,int r,int x){
int mid=(l+r)>>1;
if (!k) return;
v[k]=max(v[k],x);
if (!ls[k]&&!rs[k]){
//cout<<l<<' '<<r<<' '<<v[k]<<endl;
ans+=(long long)(r-l+1)*v[k];
return;
}
query(ls[k],l,mid,v[k]);
query(rs[k],mid+1,r,v[k]);
if (!ls[k]) ans+=(long long)(mid-l+1)*v[k];
if (!rs[k]) ans+=(long long)(r-mid)*v[k];
}
int main(){
//freopen("a.in","r",stdin);
n=read();
for (int i=1;i<=n;i++){
a=read();b=read();k=read();
if (a==b) continue;
insert(root,1,inf,a,b-1,k);
}
query(root,1,inf,0);
cout<<ans<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: