国际惯例的题面:

我们考虑大力DP。
首先重新定义代价为:1e13*选择数量-(总高度+总补偿)。这样我们只需要一个long long就能维护。
然后重新定义高度为heighti - i,这样我们能选择高度相同的点,同时可以把无论如何也不会被选择的点扔掉(这样他们的高度<0)。
之后就是转移,我们枚举i前面的被选择的点j,我们要满足的东西有:hj<=hi。
考虑我们再次选择一个点会产生怎样的代价,显然最终的答案一定是一个阶梯状的东西,所以我们选择了i之后之后所有点的高度相对于仅选择j都会上升(hi-hj)。
于是我们就可以转移了,fi=max{fj+(hi-hj)*(n-i+1)}(hj<=hi)+cost[i],cost[i]为单点价值减去选i的补偿代价。于是你可以写对拍用的n^2暴力了。
仔细观察这个转移方程,显然是一个可斜率优化的方程,我们可以把hi当成x,把fi当成j,把(n-i+1)当成a,把1当成b,这样最优答案就是ax+by的形式了。
因为hi不满足单调性,所以我们需要set维护凸包
考虑到我们还有hj<=hi的限制,所以需要再套一层cdq分治......
注意:
cdq分治在排序的时候不能只排单一关键字,需要做双关键字排序,否则会导致一些能更新的东西无法更新。
然后发现你这么写并不能AC,因为常数太大......
代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<set>
  6 #include<cmath>
  7 #include<vector>
  8 #define debug cout
  9 typedef long long int lli;
 10 using namespace std;
 11 const int maxn=1e5+1e2;
 12 const lli mul = 1e13+1e10;
 13
 14 namespace Convex {
 15     int cmp; // 0 compare x , 1 compare slope .
 16     struct Point {
 17         lli x,y;
 18         long double slop;
 19         friend bool operator < (const Point &a,const Point &b) {
 20             if( !cmp ) return a.x != b.x ? a.x < b.x : a.y < b.y;
 21             return a.slop > b.slop;
 22         }
 23         friend Point operator - (const Point &a,const Point &b) {
 24             return (Point){a.x-b.x,a.y-b.y};
 25         }
 26         friend long double operator * (const Point &a,const Point &b) {
 27             return (long double)a.x * b.y - (long double)b.x * a.y;
 28         }
 29         inline lli calc(lli a,lli b) const {
 30             return a * x + b * y;
 31         }
 32     };
 33     set<Point> st;
 34
 35     inline void Pop_right(set<Point>::iterator nxt,const Point &p) {
 36         set<Point>::iterator lst;
 37         while(1) {
 38             nxt = st.lower_bound(p);
 39             lst = nxt , ++nxt;
 40             if( nxt == st.end() ) return;
 41             if( lst->x == p.x ) {
 42                 if( p.y > lst->y ) st.erase(lst);
 43                 else break;
 44             }
 45             else {
 46                 if( (*lst-p) * (*nxt-*lst) < 0 ) return;
 47                 st.erase(lst);
 48             }
 49         }
 50     }
 51     inline void Pop_left(set<Point>::iterator prv,const Point &p) {
 52         set<Point>::iterator lst;
 53         prv = st.lower_bound(p) , --prv;
 54         if( prv == st.begin() && prv->x == p.x ) return void(st.erase(prv));
 55         while(prv!=st.begin()) {
 56             prv = st.lower_bound(p) , --prv;
 57             lst = prv , --prv;
 58             if( p.x == lst->x ) {
 59                 if( p.y > lst->y ) st.erase(lst);
 60                 else break;
 61                 continue;
 62             }
 63             else {
 64                 if( (*lst-*prv) * (p-*lst) < 0 ) break;
 65                 st.erase(lst);
 66             }
 67         }
 68     }
 69     inline bool fail(const Point &p) {
 70         set<Point>::iterator it = st.lower_bound((Point){p.x,0,0});
 71         if( it != st.end() && it->x == p.x ) {
 72             if( it->y >= p.y ) return 1; // p is useless at all .
 73             else return 0; // p must be on convex .
 74         }
 75         if( it != st.end() && it != st.begin() ) {
 76             set<Point>::iterator prv = it; --prv;
 77             if( ( p - *prv ) * (*it - p ) > 0  ) return 1;
 78         }
 79         return 0;
 80     }
 81     inline void insert(const Point &p) {
 82         cmp = 0;
 83         if( fail(p) ) return;
 84         set<Point>::iterator prv,nxt,lst=st.lower_bound(p);
 85         if(lst!=st.begin()) Pop_left(--lst,p);
 86         lst=st.lower_bound(p);
 87         if(lst!=st.end()) Pop_right(lst,p);
 88         st.insert(p) , lst = st.find(p);
 89         if(lst!=st.begin()) {
 90             prv = lst , --prv;
 91             Point x = *prv;
 92             x.slop = (long double)( p.y - x.y ) / ( p.x - x.x );
 93             st.erase(prv) , st.insert(x);
 94         }
 95         nxt = lst = st.find(p) , ++nxt;
 96         if(nxt!=st.end()) {
 97             Point x = p , n = *nxt;
 98             x.slop = (long double)( n.y - x.y ) / ( n.x - x.x );
 99             st.erase(lst) , st.insert(x);
100         } else {
101             Point x = p;
102             x.slop = -1e18;
103             st.erase(lst) , st.insert(x);
104         }
105     }
106     inline lli query(const lli &k) {
107         cmp = 1;
108         set<Point>::iterator it = st.lower_bound((Point){0,0,(long double)-k}); // it can't be st.end() if st isn't empty .
109         if( it==st.end() ) return 0;
110         lli ret = it->calc(k,1);
111         if( it != st.begin() ) {
112             --it;
113             ret = max( ret , it->calc(k,1) );
114         }
115         ++it; if( ++it!=st.end() ) ret = max( ret , it->calc(k,1) );
116         return ret;
117     }
118     inline void clear() {
119         st.clear() , cmp = 0;
120     }
121 }
122
123 lli ina[maxn],inb[maxn],f[maxn],cst[maxn],ans,add; // f[id] .
124 bool isl[maxn];
125 int n;
126
127 int cmp; // 0 compare height , 1 compare id .
128 struct Node {
129     lli hei,id;
130     friend bool operator < (const Node &a,const Node &b) {
131         if( cmp ) return a.id != b.id ? a.id < b.id : a.hei < b.hei;
132         else return a.hei != b.hei ? a.hei < b.hei : a.id < b.id;
133     }
134 }ns[maxn];
135
136 vector<Node> vec;
137
138 inline void solve(vector<Node> &vec) {
139     if( vec.size() <= 1 ) {
140         if( vec.size() ) f[vec[0].id] = max( f[vec[0].id] , cst[vec[0].id] );
141         return;
142     }
143     vector<Node> vl,vr;
144     const unsigned mid = vec.size() >> 1;
145     for(unsigned i=0;i<mid;i++) vl.push_back(vec[i]);
146     for(unsigned i=mid;i<vec.size();i++) vr.push_back(vec[i]);
147     solve(vl);
148     for(unsigned i=0;i<vl.size();i++) isl[vl[i].id] = 1;
149     for(unsigned i=0;i<vr.size();i++) isl[vr[i].id] = 0;
150     cmp = 1 , sort(vec.begin(),vec.end()) , Convex::clear();
151     for(unsigned i=0;i<vec.size();i++) {
152         if( isl[vec[i].id] ) {
153             Convex::insert((Convex::Point){vec[i].hei,f[vec[i].id],0});
154         } else {
155             f[vec[i].id] = max( f[vec[i].id] , cst[vec[i].id] + Convex::query(n-vec[i].id+1));
156         }
157     }
158     solve(vr);
159 }
160
161 int main() {
162     static lli sel,lst;
163     scanf("%d",&n) , add = (lli) n * ( n + 1 ) >> 1;
164     for(int i=1;i<=n;i++) scanf("%lld",ina+i) , ina[i] -= i;
165     for(int i=1;i<=n;i++) {
166         scanf("%lld",inb+i);
167         if( ina[i] >= 0 ) {
168             cst[i] = mul - inb[i] - ina[i] * ( n - i + 1 ) ,
169             vec.push_back((Node){ina[i],i});
170         }
171     }
172     cmp = 0 , sort(vec.begin(),vec.end());
173     solve(vec);
174     for(int i=1;i<=n;i++) ans = max( ans , f[i] );
175     ans -= add;
176     sel = ( ans + mul ) / mul;
177     lst = mul * sel - ans;
178     printf("%lld %lld\n",sel,lst);
179     return 0;
180 }

View Code

另外这个东西其实不用平衡树维护凸包,如果你外层分治位置,内层分治height的话,height就会有序,这样只需要写一个普通凸包就好了......
在BZOJ上只有这样才能AC......//QAQ
代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define debug cout
  7 typedef long long int lli;
  8 typedef long double ldb;
  9 using namespace std;
 10 const int maxn=1e5+1e2;
 11 const lli mul = 1e13 + 1e10;
 12
 13
 14 struct Convex {
 15     struct Point {
 16         lli x,y;
 17         friend Point operator - (const Point &a,const Point &b) {
 18             return (Point){a.x-b.x,a.y-b.y};
 19         }
 20         friend ldb operator * (const Point &a,const Point &b) {
 21             return (ldb)a.x*b.y - (ldb)a.y*b.x;
 22         }
 23         friend lli operator ^ (const Point &a,const Point &b) {
 24             return a.x * b.x + a.y * b.y;
 25         }
 26     }ps[maxn];
 27     int top;
 28     inline void push(const Point &p) {
 29         while( top > 1 ) {
 30             if( p.x == ps[top].x && p.y > ps[top].y ) --top;
 31             else if( ( ps[top] - ps[top-1] ) * ( p - ps[top] ) > 0 ) --top;
 32             else break;
 33         }
 34         if( top == 1 && p.x == ps[top].x && p.y > ps[top].y ) --top;
 35         if( !top || p.x != ps[top].x ) ps[++top] = p;
 36     }
 37     inline lli query(const Point &p) {
 38         int l = 1 , r = top , lmid , rmid;
 39         while( r > l + 2 ) {
 40             lmid = ( l + l + r ) / 3 , rmid = ( l + r + r ) / 3;
 41             if( ( p ^ ps[lmid] ) < ( p ^ ps[rmid] ) ) l = lmid;
 42             else r = rmid;
 43         }
 44         lli ret = 0;
 45         for(int i=l;i<=r;i++) ret = max( ret , p ^ ps[i] );
 46         return ret;
 47     }
 48     inline void clear() {
 49         top = 0;
 50     }
 51 }con;
 52
 53 lli ina[maxn],inb[maxn],f[maxn],cst[maxn],ans,add; // f[id] .
 54 bool isl[maxn];
 55 int n;
 56
 57 int cmp; // 0 compare height , 1 compare id .
 58 struct Node {
 59     lli hei,id;
 60     friend bool operator < (const Node &a,const Node &b) {
 61         if( cmp ) return a.id != b.id ? a.id < b.id : a.hei < b.hei;
 62         else return a.hei != b.hei ? a.hei < b.hei : a.id < b.id;
 63     }
 64 }ns[maxn];
 65
 66 vector<Node> vec;
 67
 68 inline void solve(vector<Node> &vec) {
 69     if( vec.size() <= 1 ) {
 70         if( vec.size() ) f[vec[0].id] = max( f[vec[0].id] , cst[vec[0].id] );
 71         return;
 72     }
 73     vector<Node> vl,vr;
 74     const unsigned mid = vec.size() >> 1;
 75     for(unsigned i=0;i<mid;i++) vl.push_back(vec[i]);
 76     for(unsigned i=mid;i<vec.size();i++) vr.push_back(vec[i]);
 77     solve(vl);
 78     for(unsigned i=0;i<vl.size();i++) isl[vl[i].id] = 1;
 79     for(unsigned i=0;i<vr.size();i++) isl[vr[i].id] = 0;
 80     cmp = 0 , sort(vec.begin(),vec.end()) , con.clear();
 81     for(unsigned i=0;i<vec.size();i++) {
 82         if( isl[vec[i].id] ) {
 83             con.push((Convex::Point){vec[i].hei,f[vec[i].id]});
 84         } else {
 85             f[vec[i].id] = max( f[vec[i].id] , cst[vec[i].id] + con.query((Convex::Point){n-vec[i].id+1,1}));
 86         }
 87     }
 88     solve(vr);
 89 }
 90
 91 int main() {
 92     static lli sel,lst;
 93     scanf("%d",&n) , add = (lli) n * ( n + 1 ) >> 1;
 94     for(int i=1;i<=n;i++) scanf("%lld",ina+i) , ina[i] -= i;
 95     for(int i=1;i<=n;i++) {
 96         scanf("%lld",inb+i);
 97         if( ina[i] >= 0 ) {
 98             cst[i] = mul - inb[i] - ina[i] * ( n - i + 1 ) ,
 99             vec.push_back((Node){ina[i],i});
100         }
101     }
102     cmp = 1 , sort(vec.begin(),vec.end());
103     solve(vec);
104     for(int i=1;i<=n;i++) ans = max( ans , f[i] );
105     ans -= add;
106     sel = ( ans + mul ) / mul;
107     lst = mul * sel - ans;
108     printf("%lld %lld\n",sel,lst);
109     return 0;
110 }

View Code

转载于:https://www.cnblogs.com/Cmd2001/p/8686125.html

Bzoj2149拆迁队:cdq分治 凸包相关推荐

  1. bzoj2149 拆迁队 CDQ分治

    首先对于任意a[i]都减去一个i转化为单调不下降序列方便操作,设新的d[i]=a[i]-i.然后第一问二分或者BIT水过去,设f[i]表示i为结尾的最长序列. 然后设g[i]为保留i时的最优值,那么可 ...

  2. 【分治+斜率优化】BZOJ2149拆迁队 CF660F Bear and Bowling 4

    BZOJ2149拆迁队 [题目] 原题地址 题目大意不想写. [题目分析] 斜率优化的dp是显然的,然后就是怎么维护的问题了. [解题思路] 这题显然就是一个斜率优化的dp,然后分治的时候维护一下凸壳 ...

  3. bzoj2149拆迁队 斜率优化dp+分治

    2149: 拆迁队 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 397  Solved: 177 [Submit][Status][Discuss ...

  4. BZOJ 2961 共点圆 CDQ分治+凸包

    题目大意:给定平面,多次插入点和圆,每次插入点时询问当前插入的点是否在之前插入的所有圆中并且至少在一个圆中 直接用数据结构维护这些点和圆不是很好写,我们考虑CDQ分治 对于每层分治,我们需要对于[mi ...

  5. 【BZOJ2149】拆迁队,分治+斜率优化DP

    传送门 思路还不错的一道题目,难度不大,但是我在写的时候出了一些细节上的错误 显然题目中的两问都可以通过DP来解决 f[i]f[i]表示保留旧房子ii时,1-i1-i最多能保留多少个旧房子 g[i]g ...

  6. BZOJ2149 : 拆迁队

    设$c[i]=g[i]+\frac{i(i+1)}{2}-a[i]\times i-a[i]$,$d[i]=a[i]-i$ $f[i]$表示以$i$为结尾最多保留多少个建筑,则 $f[i]=\max( ...

  7. bzoj 2149 拆迁队 斜率优化+cdq分治

    题面 题目传送门 解法 从来没写过这样的-- 第一问非常简单,能够从 j j j转移到 i i i的条件显然为 a [ i ] − a [ j ] ≥ i − j a[i]-a[j]≥i-j a[i] ...

  8. bzoj2961 共点圆 (CDQ分治, 凸包)

    /* 可以发现可行的圆心相对于我们要查询的点是在一个半平面上, 然后我们要做的就是动态维护凸壳然后用这个半平面去切它 看看是否是在合法的那一面然后cdq分治就可以了代码基本是抄的,*/#include ...

  9. 洛谷P3122 [USACO15FEB]圈住牛Fencing the Herd(计算几何+CDQ分治)

    题面 传送门 题解 题目转化一下就是所有点都在直线\(Ax+By-C=0\)的同一侧,也就可以看做所有点代入\(Ax+By-C\)之后的值符号相同,我们只要维护每一个点代入直线之后的最大值和最小值,看 ...

最新文章

  1. 十佳自由Linux物理工具
  2. 开发chrome 插件, background.js中 console log 看不到解决方法
  3. 把佳佳的博客搬出去了
  4. JavaScript之apply()和call()的区别
  5. jwt重放攻击_4个点搞懂JWT、JWS、JWE
  6. [css] 写出你遇到过IE6/7/8/9的BUG及解决方法
  7. GD32 使用stm32 固件库
  8. linux centos7 安装zookeeper
  9. 转换json_使用Java将JSON转换为POJO
  10. c语言删除元素1116,C语言网蓝桥杯1116 IP判断
  11. Setup JIRA Service Desk 3.9.2 on Oracle Linux 6.8
  12. 基于stc15f2k60s2芯片单片机编程(串口超声波时间)
  13. 关于网页数据导入excel问题
  14. MP6002使用说明
  15. unity视频教程【高清+精选】大放送
  16. ES6 对象的解构赋值
  17. 【转】王阳明:耐住寂寞,守得花开
  18. 神经网络整合算法是什么,神经网络整合算法实例
  19. EOJ Monthly 2020.11 Sponsored by TuSimple F题“天桥”题解
  20. 达梦数据备份还原(物理逻辑)

热门文章

  1. nextLine()的坑
  2. Android 4.0发布了
  3. malloc函数及memset函数用法详解
  4. ShardingSphere-JDBC执行原理
  5. linux(ubuntu)无法连接网络
  6. git冲突出现的原因及解决方案
  7. CVPR2018 | R(2+1)D结构:视频动作识别中的时空卷积深度探究
  8. CentOS 8 启动盘的安装
  9. 我眼中的微商为什么要用微商系统
  10. 教你炒股票18:不被面首的雏男是不完美的