【BZOJ4636】蒟蒻的数列
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
2 5 1
9 10 4
6 8 2
4 6 3
Sample Output
16
题解:当一段区间先进行操作l,r,a,再进行操作l,r,b时,最后的结果一定是a,b中的最大值,那我们直接离线处理。对于每段区间,直接让它变成所有包含这段区间的操作中的最大值。用multiset维护一下就好了
#include <cstdio> #include <cstring> #include <iostream> #include <set> #include <algorithm> using namespace std; typedef long long ll; const int maxn=40010; int n,tot; ll ans; multiset<ll> s; struct node { int org,k; ll v,val; }p[maxn<<1]; bool cmp(node a,node b) { return a.v<b.v; } int main() { scanf("%d",&n); int i,j; for(i=1;i<=n;i++) { scanf("%lld%lld%lld",&p[tot+1].v,&p[tot+2].v,&p[tot+1].val); if(p[tot+1].v==p[tot+2].v) continue; p[tot+2].val=p[tot+1].val,p[tot+2].k=1,tot+=2; } sort(p+1,p+tot+1,cmp); multiset<ll>::iterator it; for(i=1;i<=tot;i++) { if(p[i].v!=p[i-1].v&&!s.empty()) { it=s.end(),--it; ans+=(p[i].v-p[i-1].v)*(*it); } if(p[i].k) it=s.find(p[i].val),s.erase(it); else s.insert(p[i].val); } printf("%lld",ans); return 0; }