计蒜客- Trace 二分
链接:https://nanti.jisuanke.com/t/31459
题意:有n次海浪,每次海浪会产生两段轨迹(0,y)到(x,y)和(x,0)到(x,y),后面的海浪会将前面的在(0,0)到(x,y)之间区域的海浪轨迹覆盖掉,问最后剩余的轨迹长度。保证后面的海浪不会完全覆盖其他海浪。
思路:根据题意,后面的点要么比前面的点高,要么比他们长。从后向前统计,用set记录每一个已经统计过长度的线段。统计一条线段的有效长度,要减去被覆盖的部分,方法:找到已经统计过的线段中 比新线段小的所有线段的最大值(用二分找),这个值就是新线段被覆盖的部分,减去这个值得到有效值,如果没有,就表明新线段没有被覆盖,直接统计。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <algorithm> #include <vector> #include <set> #define ll long long #define maxn 50009 #define rep1(i,a,b) for(int i=a;i<=b;i++) #define rep2(i,a,b) for(int i=a;i>=b;i--) using namespace std; vector<int> xvec, yvex; int n; ll callength(vector<int> vec) { set<int> st; ll ans = 0; set<int>::iterator it; rep2(i, n - 1, 0) { it = st.lower_bound(vec[i]); if (it == st.begin()) { ans += vec[i]; } else { it--; ans += vec[i] - *it; } st.insert(vec[i]); } return ans; } int main() { int x, y; scanf("%d",&n); rep1(i, 1, n) { scanf("%d%d", &x, &y); xvec.push_back(x); yvex.push_back(y); } printf("%lld", callength(xvec) + callength(yvex)); return 0; }