BZOJ 4636 蒟蒻的数列

4636: 蒟蒻的数列

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 618  Solved: 271
[Submit][Status][Discuss]

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

HINT

 

Source

 

动态开点线段树与下标的传递,我们知道线段树的复杂度是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;
}

  

posted @ 2018-05-18 22:52  zhangenming  阅读(212)  评论(0编辑  收藏  举报