ACM-ICPC 2018 徐州赛区网络预赛 G. Trace (线段树维护)

题意
你在海滩上有浪花,所有的浪花都是矩形的,当一个浪花来了之后,就会覆盖他的前一个浪花,问你最后浪花的周长和
思路
我们从后往前来,这样的话,我们处理的都是会留下来的,怎样的会留下来呢?这里写图片描述
首先我们先看1号点和2号点,由图我们可以很明显的看出1号点会被淹没,而1`和1“他们不会被淹没,所以对于我们当前的值来说,我们维护一下大于他的x的最大的y,和大于他的y坐标的最大的x,这两个值,然后每次查询之后观察我们当前的x[i],和y[i]的关系,加上贡献就好,具体怎么维护,我们把所有点离散下来,建两颗线段树,1颗以x的坐标为线段树的区间,y为线段树的权值维护y的最大值,x坐标反之,之后对于查询*(x,y),我们查 (x,n)区间中的最大值,二维变一维了就。
代码

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define rrep(i,j,k) for(int i=j;i>=k;i--)
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
typedef long long ll;
using namespace std;
const int MAXN = 2e5+11;
const ll oo = 0x3f3f3f3f3f3f3f3f;
const ll ooo= 0x3f3f3f3f;
const int MOD = 1e9+7;
ll read(){
  ll x=0,f=1;register char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  return x*f;
}
struct ST{
    #define lc o<<1
    #define rc o<<1|1
    ll mx[MAXN<<2];
    void pu(int o){
        mx[o]=max(mx[lc],mx[rc]);
    }
    void update(int o,int l,int r,int k,ll v){
        if(l==r){
            mx[o]=max(mx[o],v);
            return;
        }
        int mid=l+r>>1;
        if(k<=mid) update(lc,l,mid,k,v);
        else update(rc,mid+1,r,k,v);
        pu(o);
    }
    ll query(int o,int l,int r,int L,int R){
        if(L<=l&&r<=R) return mx[o];
        int mid=l+r>>1;
        ll ans=0;
        if(L<=mid) ans=max(ans,query(lc,l,mid,L,R));
        if(R>mid) ans=max(ans,query(rc,mid+1,r,L,R));
        return ans;
    }
}st[2];

struct QAQ{
    int x, y;
    int _x,_y;
    QAQ(int Q=0,int A=0){
        x=Q;
        y=A;
    }
}a[MAXN]; 
int xx[MAXN],yy[MAXN],n;
int main(){
    while(cin>>n){
        int cnt=0;
        rep(i,1,n){
            int x=read();
            int y=read();
            a[i]=QAQ(x,y);
            xx[++cnt]=x;
            yy[cnt]=y;
        }
        sort(xx+1,xx+1+cnt);
        sort(yy+1,yy+1+cnt);
        rep(i,1,n){
            a[i]._x=lower_bound(xx+1,xx+1+cnt,a[i].x)-xx;
            a[i]._y=lower_bound(yy+1,yy+1+cnt,a[i].y)-yy; 
        }
      //  for(int i = 1 ; i <= n ; i++) printf("%d %d\n",a[i]._x,a[i]._y);
        rep(i,0,1) memset(st[i].mx,0,sizeof st[i].mx);
        //st[0]: x坐标下最大的y
        //st[1]: y坐标下最大的x 
        ll ans=0;
        rrep(i,n,1){
            int x=a[i].x;
            int y=a[i].y;
            int xid=a[i]._x;
            int yid=a[i]._y;
            ll t1=st[1].query(1,1,cnt,yid,cnt); 
            if(t1<x) ans+=x-t1;
            st[1].update(1,1,cnt,yid,x);
            ll t2=st[0].query(1,1,cnt,xid,cnt);
            if(t2<y) ans+=y-t2;
            st[0].update(1,1,cnt,xid,y); 
        }
        println(ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wjmwsgj/article/details/82694834
今日推荐