zoukankan      html  css  js  c++  java
  • 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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    linux音频alsa-uda134x驱动文档阅读之一转自http://blog.csdn.net/wantianpei/article/details/7817293
    linux音频alsa-uda134x驱动分析之二(时钟)
    linux下定时器介绍1
    linux下定时器介绍2--timer_create等函数集的使用示例
    linux 获取时间后--自定义时间格式
    linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction
    高通QMI协议
    linux sigaction 函数 用法释义
    NB-iot 和 emtc两种技术区别
    如何调整Linux内核启动中的驱动初始化顺序-驱动加载优先级
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14149686.html
Copyright © 2011-2022 走看看