zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 92 (Rated for Div. 2) 选讲

    https://codeforces.ml/contest/1389/problem/F

    法一:dp,所有区间按右端点排序,依次考虑“如果最后一个区间为该区间”的最优情况,它(叫做A)可以从一个“右端点比A的左端点小”的异类区间B转移过来,但是同时可以顺便把“B的右端点以右”的同类区间算上。算上同类区间可以用线段树维护:每次计算完一个区间[L,R]后,把右端点小于L的所有异类区间的dp值+1。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4  
     5 int n;
     6 const int maxn=400011;
     7  
     8 struct SEG
     9 {
    10     int l,r,t;
    11     bool operator < (const SEG &b) const
    12     {
    13         return r<b.r;
    14     }
    15 }seg[maxn];
    16 int lisa[maxn<<1],li=0;
    17  
    18 int dp[maxn],contain[maxn];
    19 struct SmtNode{int Max,add;};
    20 struct SMT
    21 {
    22     SmtNode a[maxn<<2];
    23     int n;
    24     SMT() {n=0;}
    25     void clear(int N) {n=N;}
    26 //    int ls(int x) {return x<<1;}
    27 //    int rs(int x) {return (x<<1)|1;}
    28     #define ls(x) (x<<1)
    29     #define rs(x) ((x<<1)|1)
    30     void up(int x) {a[x].Max=max(a[ls(x)].Max,a[rs(x)].Max);}
    31     void addsingle(int x,int v) {a[x].Max+=v; a[x].add+=v;}
    32     void down(int x) {if (a[x].add>0) {addsingle(ls(x),a[x].add); addsingle(rs(x),a[x].add); a[x].add=0;} }
    33     void Insert(int x,int L,int R,int p,int v)
    34     {
    35         if (L==R) {a[x].Max=max(a[x].Max,v); return;}
    36         down(x);
    37         int mid=(L+R)>>1;
    38         if (p<=mid) Insert(ls(x),L,mid,p,v);
    39         else Insert(rs(x),mid+1,R,p,v);
    40         up(x);
    41     }
    42     void insert(int p,int v) {Insert(1,0,n,p,v);}
    43     int QPreMax(int x,int L,int R,int p)
    44     {
    45         if (R<=p) return a[x].Max;
    46         down(x);
    47         int mid=(L+R)>>1;
    48         if (p<=mid) return QPreMax(ls(x),L,mid,p);
    49         return max(QPreMax(ls(x),L,mid,p),QPreMax(rs(x),mid+1,R,p));
    50     }
    51     int qPreMax(int p) {return QPreMax(1,0,n,p);}
    52     void Add(int x,int L,int R,int ql,int qr,int v)
    53     {
    54         if (ql<=L && R<=qr) {addsingle(x,v); return;}
    55         down(x);
    56         int mid=(L+R)>>1;
    57         if (ql<=mid) Add(ls(x),L,mid,ql,qr,v);
    58         if (qr>mid) Add(rs(x),mid+1,R,ql,qr,v);
    59         up(x);
    60     }
    61     void add(int L,int R,int v) {if (L<=R) Add(1,0,n,L,R,v);}
    62 }s[2];
    63  
    64 int main()
    65 {
    66     scanf("%d",&n);
    67     for (int i=1;i<=n;i++)
    68     {
    69         scanf("%d%d%d",&seg[i].l,&seg[i].r,&seg[i].t);
    70         seg[i].t--;
    71         lisa[++li]=seg[i].l;
    72         lisa[++li]=seg[i].r;
    73     }
    74     sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1;
    75     for (int i=1;i<=n;i++)
    76     {
    77         seg[i].l=lower_bound(lisa+1,lisa+1+li,seg[i].l)-lisa;
    78         seg[i].r=lower_bound(lisa+1,lisa+1+li,seg[i].r)-lisa;
    79     }
    80     sort(seg+1,seg+1+n);
    81 //    for (int i=1;i<=n;i++) cout<<"NO"<<i<<' '<<seg[i].l<<' '<<seg[i].r<<' '<<seg[i].t<<endl;
    82     
    83     s[0].clear(li); s[1].clear(li);
    84     dp[0]=0;
    85     for (int i=1;i<=n;i++)
    86     {
    87         bool ty=seg[i].t;
    88         dp[i]=s[ty^1].qPreMax(seg[i].l-1)+1;
    89         s[ty].insert(seg[i].r,dp[i]);
    90         s[ty^1].add(0,seg[i].l-1,1);
    91 //        cout<<i<<' '<<dp[i]<<endl;
    92     }
    93     
    94     int ans=0;
    95     for (int i=1;i<=n;i++) ans=max(ans,dp[i]);
    96     printf("%d
    ",ans);
    97     return 0;
    98 }
    View Code

    法二:每个区间看作一个结点,会冲突的区间都连一条边,会形成一个二分图,目标是找最大独立集,转换为找最大匹配。复杂度不允许用二分图的算法。可将1类的区间按右端点升序,依次考虑能否匹配,对每个1类区间A,在所有能与之匹配的2类区间中贪心找右端点最小的即可。(枚举1类区间A的过程中会将“左端点小于A的右端点”的2类区间的右端点不停地丢入数据结构中,我们希望数据结构中存留下来的这些“右端点”们尽可能大,才能满足后面更大的“1类区间的左端点”)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 
     5 int n;
     6 struct SEG{int l,r;};
     7 vector<SEG> seg[2];
     8 multiset<int> s;
     9 
    10 int main()
    11 {
    12     scanf("%d",&n);
    13     for (int i=1,l,r,t;i<=n;i++)
    14     {
    15         scanf("%d%d%d",&l,&r,&t);
    16         seg[t-1].push_back((SEG){l,r});
    17     }
    18     sort(seg[0].begin(),seg[0].end(),[](SEG a,SEG b) {return a.r<b.r;});
    19     sort(seg[1].begin(),seg[1].end(),[](SEG a,SEG b) {return a.l<b.l;});
    20     
    21 //    cout<<endl;
    22     unsigned int j=0,ans=n;
    23     for (SEG x:seg[0])
    24     {
    25         while (j<seg[1].size() && seg[1][j].l<=x.r) s.insert(seg[1][j].r),j++;
    26         auto it=s.lower_bound(x.l);
    27         if (it==s.end()) continue;
    28 //        cout<<x.l<<' '<<x.r<<' '<<*it<<endl;
    29         s.erase(it);
    30         ans--;
    31     }
    32     printf("%d
    ",ans);
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    上门量体不能停,量品打造“一人一版”的私人定制衬衫,半年覆盖30个城市
    直击中小互联网企业痛点,程序员客栈推出短期雇佣功能
    现在,培训老师也有可能是你未来的 Boss
    【蓝领日志】捷库,给B端提供蓝领员工的标准化培训工具
    【调研】华图教育:领跑公职培训市场
    社区服务中心+护理员培训+云平台,中康行健“一体两翼”构建养老生态体系
    餐厅孵化器“优粮生活”,用孵化模式打造统一独立外卖品牌
    语培市场热度不减,“手韩”背后的垂直领域空间在哪?
    母基金_百度百科
    小编亲测杭州最火的海南鸡饭,最好吃的居然是……-搜狐吃喝!!!
  • 原文地址:https://www.cnblogs.com/Blue233333/p/13430868.html
Copyright © 2011-2022 走看看