• 51nod 1611 金牌赛事(动态规划 + 线段树)


    分析:看起来有点像最大权闭合图,然而复杂度太高。。。

    正解是dp,设dp[i]为考虑前i条路的最大收益,则dp[i]=max{dp[j] - cost[j+1][i] + earn[j+1][i]},0<=j<=i-1,earn[j+1][i]表示在[j+1,i]之间的比赛,是个O(n^2)的dp.

    接下来考虑优化这个dp.维护一个线段树,当扫到i时,树中满足a[j] = dp[j] - cost[j+1][i] + earn[j+1][i],先将比赛按右端点排序,然后每扫到一个右端点为i的比赛,将所有j<l的a[j] 加上earn,将所有j<i的a[i]减去c[i],然后更新dp[i]为[0,i-1]的最大值。复杂度为O(nlogn)。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cstdio>
      5 using namespace std;
      6 typedef long long ll;
      7 const int maxn=2e5+5;
      8 const ll inf = 1e18;
      9 struct Contest{
     10     int l,r;
     11     ll earn;
     12 }p[maxn];
     13 int n, m;
     14 //bool Cmp(Pair a,Pair b){return a.r-a.l<b.r-b.l;}
     15 bool Cmp(Contest a, Contest b){return a.r < b.r;}
     16 class segTree{
     17     ll a[maxn],s[maxn*4],tag[maxn*4];
     18 public:
     19     segTree(){memset(a,0,sizeof(a));}
     20     void build(int node,int begin,int end){
     21         tag[node]=0;
     22         if(begin==end){
     23             s[node]=a[begin];
     24         }else{
     25             build(2*node,begin,(begin+end)/2);
     26             build(2*node+1,(begin+end)/2+1,end);
     27             s[node]=max(s[2*node],s[2*node+1]);
     28         }
     29     }
     30     void pushdown(int node,int begin,int end){
     31         if(begin==end){
     32             s[node]+=tag[node];
     33             a[begin]=s[node];
     34         }else{
     35             tag[2*node]+=tag[node];
     36             tag[2*node+1]+=tag[node];
     37             s[node]+=tag[node];
     38         }
     39         tag[node]=0;
     40     }
     41     void Change(int node,int begin,int end,int left,int right,ll add){
     42         if(begin>=left&&end<=right){
     43             tag[node]+=add;
     44         }else{
     45             pushdown(node,begin,end);
     46             int m=(begin+end)/2;
     47             if(!(right<begin||left>m)){
     48                 Change(2*node,begin,m,left,right,add);
     49             }
     50             if(!(right<m+1||left>end)){
     51                 Change(2*node+1,m+1,end,left,right,add);
     52             }
     53             s[node] = max(s[2 * node] + tag[2 * node], s[2 * node + 1] + tag[2 * node + 1]);
     54         }
     55     }
     56     ll query(int node,int begin,int end,int left,int right){
     57         pushdown(node,begin,end);
     58         if(begin > right || end < left)return -inf;
     59         if(begin==end)return a[begin];
     60         if(begin >= left && end <= right)return s[node];
     61         ll q1 = query(2 * node, begin, (begin + end) / 2, left, right);
     62         ll q2 = query(2 * node + 1, (begin + end) / 2 + 1, end, left, right);
     63         return max(q1, q2);
     64     }
     65     void Print(){
     66         for(int i = 0; i <= n; i++){
     67             cout<<query(1, 0, n, i, i)<<' ';
     68         }
     69         cout<<endl;
     70     }
     71 }st;
     72 
     73 ll c[maxn], f[maxn];
     74 int main(){
     75 //    freopen("e:\in.txt","r",stdin);
     76     scanf("%d%d",&n,&m);
     77     for(int i = 1; i <= n; i++)scanf("%lld",&c[i]);
     78     for(int i = 0; i < m; i++)scanf("%d%d%lld",&p[i].l,&p[i].r,&p[i].earn);
     79     sort(p, p + m, Cmp);
     80     int idx = 0;
     81     st.build(1, 0, n);
     82     f[0] = 0;
     83     for(int i = 1; i <= n; i++){
     84         while(idx < m && p[idx].r <= i){
     85             st.Change(1, 0, n, 0, p[idx].l - 1, p[idx].earn);
     86 //            st.Print();
     87             idx++;
     88         }
     89         st.Change(1, 0, n, 0, i - 1, -c[i]);
     90 //        st.Print();
     91         f[i] = st.query(1, 0, n, 0, i - 1);
     92         f[i] = max(f[i - 1], f[i]);
     93         st.Change(1, 0, n, i, i, f[i]);
     94 //        st.Print();
     95 //        cout<<"*********"<<endl;
     96     }
     97 //    for(int i = 0; i <= n; i++)cout<<f[i]<<endl;
     98     cout<<f[n]<<endl;
     99     return 0;
    100 }
  • 相关阅读:
    Django学习笔记
    禁用Win10自带截图工具快捷键(Shift+Win+S)
    Linux基础知识
    Ubuntu中配置Python虚拟环境Virtualenv
    PyCharm 格式化代码 常用快捷键
    你不得不知道的HashMap面试连环炮
    大型互联网公司分布式ID方案总结
    Java程序员必会常用Linux速查手册
    面试题:InnoDB中一棵B+树能存多少行数据?
    C语言:标准IO_fopen( )、fclose() ①
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7891937.html
Copyright © 2020-2023  润新知