bzoj1645

来源:互联网 发布:steam淘宝充值卡便宜 编辑:程序博客网 时间:2024/05/18 17:43

分析:具体就是做扫描线,然后把坐标存储下来离散化以后,在线段树上打标记。。连续一段直接横坐标乘最小纵坐标就好。

#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;int n,m;typedef long long ll;const int N=1e5+5;const int M=5*N;int x,y,z,tot,last;int a[N],b[N],c[N],p[N],h[N],re[N];int sum[M],delta[M];struct node{    int loc,h,f;}e[M];ll ans;bool cmp(int x,int y){    return c[x]<c[y];}bool cmp1(node a,node b){    return a.loc<b.loc;}inline void update(int x){    sum[x]=sum[x*2]+sum[x*2+1];}inline void pushdown(int x,int l,int r,int mid){    if (delta[x])    {        sum[x*2]+=delta[x]*(mid-l+1);        sum[x*2+1]+=delta[x]*(r-mid);        delta[x*2]+=delta[x];        delta[x*2+1]+=delta[x];        delta[x]=0;    }}inline void change(int x,int l,int r,int l1,int r1,int v){    int mid=(l+r)>>1;    if(l1<=l&&r<=r1)    {        sum[x]+=v*(r-l+1);        delta[x]+=v;        return;    }    pushdown(x,l,r,mid);    if (l1<=mid)change(x*2,l,mid,l1,r1,v);    if (mid+1<=r1)change(x*2+1,mid+1,r,l1,r1,v);    update(x);}inline int query(int x,int l,int r){    int mid=(l+r)>>1;    if (l==r)    {        if (sum[x])return l;        else return l-1;    }    pushdown(x,l,r,mid);    if (!sum[x*2+1])return query(x*2,l,mid);    else return query(x*2+1,mid+1,r);}int main(){    scanf("%d",&n);    fo(i,1,n)    scanf("%d%d%d",&a[i],&b[i],&c[i]),p[i]=i;    sort(p+1,p+1+n,cmp);    fo(i,1,n)    h[p[i]]=i,re[i]=c[p[i]];    fo(i,1,n)    {        x=a[i],y=b[i],z=h[i];        e[++tot].loc=x,e[tot].h=z,e[tot].f=1;        e[++tot].loc=y,e[tot].h=z,e[tot].f=2;    }    sort(e+1,e+1+tot,cmp1);    fo(i,1,tot)    {        ans+=(ll)re[last]*(ll)(e[i].loc-e[i-1].loc);        if (e[i].f==1)change(1,1,n,1,e[i].h,1);        else change(1,1,n,1,e[i].h,-1);        last=query(1,1,n);    }    printf("%lld\n",ans);    return 0;}
0 0
原创粉丝点击