2018ICPC首尔A题 Circuits(线段树)

经典套路,首先发现只有两个边,这种情况下,很容易想到使用枚举的方法,枚举第一条边,然后计算对应的第二边最优,之后对于所有情况取max

这里只有y有用并且每个矩形其实就是一条线段

对于这题,一个需要考虑的问题是,如何当我们枚举一条边的时候,计算第二边答案的时候不会计算进第一条已经穿过的矩形。

那么其实这也是另一个套路,只要我们动态加边,倒着枚举,枚举每个点时,线段树中只有后面不会被当前点穿过的边,然后再维护一个前缀和,表示每个点能穿过的边

两个答案相加就是当前枚举点的答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
vector<int> num;
vector<int> g[N];
int l[N],r[N];
int sum[N];
struct node{
    int l,r;
    int mx;
    int lazy;
}tr[N<<2];
int find(int x){
    return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r};
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void pushdown(int u){
    int x=tr[u].lazy;
    tr[u<<1].mx+=x;
    tr[u<<1|1].mx+=x;
    tr[u<<1].lazy+=x;
    tr[u<<1|1].lazy+=x;
    tr[u].lazy=0;
}
void pushup(int u){
    tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
}
void modify(int u,int l,int r,int x){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].mx+=x;
        tr[u].lazy+=x;
        return ;
    }
    if(tr[u].lazy)
        pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r,x);
    if(r>mid)
        modify(u<<1|1,l,r,x);
    pushup(u);
}
int main(){
    int n;
    ios::sync_with_stdio(false);
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        l[i]=d,r[i]=b;
        num.push_back(b);
        num.push_back(d);
    }
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    for(i=1;i<=n;i++){
        l[i]=find(l[i]);
        r[i]=find(r[i]);
        g[l[i]].push_back(r[i]);
        sum[l[i]]++,sum[r[i]+1]--;
    }
    for(i=1;i<=(int)num.size();i++){
        sum[i]+=sum[i-1];
    }
    int ans=0;
    build(1,1,(int)num.size());
    for(i=(int)num.size();i>=1;i--){
        ans=max(ans,sum[i]+tr[1].mx);
        for(auto x:g[i]){
            modify(1,i,x,1);
        }
    }
    cout<<ans<<endl;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14149686.html