2018 徐州網路賽 G 題解

ACM_e發表於2018-09-11

電波~

這題首先要倒著貼這樣 每次➕就好了 還有就是 資料太大需要離散化

然後建線段樹,根據x軸的座標建座標軸 ,看  這個點的 max(y) 有多大 如果 y[i]> max(y) 產生 貢獻 ans+=y[x]-max(x)

x軸同理 

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000001
struct ac{
  int x,y;
}b[maxn];
int a[maxn],lz[maxn],c[maxn];
int n,tot=1,t=1;
void updata(int x,int y,int l,int r,int va,int in){
   if(x==l&&y==r){
       c[in]=max(c[in],va);
       lz[in]=max(lz[in],va);
       return ;
   }
   int mid=(l+r)/2;
   if(lz[in]){
       c[in*2]=max(lz[in],c[in*2]);
       c[in*2+1]=max(lz[in],c[in*2+1]);
       lz[in*2]=max(lz[in],lz[in*2]);
       lz[in*2+1]=max(lz[in],lz[in*2+1]);
       lz[in]=0;
   }
   if(x>mid){
      updata(x,y,mid+1,r,va,in*2+1);
   }else if(y<=mid){
      updata(x,y,l,mid,va,in*2);
   }else{
      updata(mid+1,y,mid+1,r,va,in*2+1);
      updata(x,mid,l,mid,va,in*2);
   }
   c[in]=max(c[in*2],c[in*2+1]);
}
int query(int x,int l,int r,int in){
   if(l==r){
      return c[in];
   }
   int mid=(l+r)/2;
   if(lz[in]){
       c[in*2]=max(lz[in],c[in*2]);
       c[in*2+1]=max(lz[in],c[in*2+1]);
       lz[in*2]=max(lz[in],lz[in*2]);
       lz[in*2+1]=max(lz[in],lz[in*2+1]);
       lz[in]=0;
   }
   if(x>mid){
      return query(x,mid+1,r,in*2+1);
   }
   return query(x,l,mid,in*2);
}
int main(){
   cin>>n;
   for(int j=1;j<=n;j++){
      cin>>b[j].x>>b[j].y;
      a[tot++]=b[j].x;
      a[tot++]=b[j].y;
   }
   sort(a+1,a+tot);
   for(int i=2;i<tot;i++)if(a[i]!=a[i-1])a[++t]=a[i];
   long long ans=0;
   memset(c,0,sizeof(c));
   memset(lz,0,sizeof(lz));
   int l=lower_bound(a+1,a+t+1,b[n].x)-a;
   int r=lower_bound(a+1,a+t+1,b[n].y)-a;
   ans+=a[r]+a[l];
   //cout<<ans<<endl;
   updata(1,l,1,t,r,1);           // 把 1-x 全部更新成 y 的最大值(離散化之後是座標)
   for(int j=n-1;j>=1;j--){
      int l=lower_bound(a+1,a+t+1,b[j].x)-a;
      int r=lower_bound(a+1,a+t+1,b[j].y)-a;
      int i=query(l,1,t,1);
      if(i<r){
         ans+=a[r]-a[i];
      }
      int ll=1,rr=l;
      int mi=1e9;
      while(ll<=rr){                 //我們要找比y小的最小的x 這樣才會有貢獻
         int mid=(ll+rr)/2;
         i=query(mid,1,t,1);
         if(i<r){
            mi=min(mi,mid);         // 說明這個點的mid這個點的y < 當前j 點的y 可以產生貢獻取min(x)  
            rr=mid-1;
         }else ll=mid+1;
      }
      if(mi!=1e9){
         ans+=a[l]-a[ll-1];
      }
      updata(1,l,1,t,r,1);
   }
   cout<<ans<<endl;
}

 

相關文章