线段树和DP的综合题,思路非常巧妙~~~acdream的比赛我一般都会做,因为时间点比较好,不想CF的时间。。。当时比赛的时候不会做(当时我还不会线段树,其实现在也没学好QAQ),看了题解以后补上。。。。题解在此ACdream题解链接。
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define maxn 100005 #define eps 1e-6 #define mod 1000000007 #define INF 99999999 #define lowbit(x) (x&(-x)) #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; struct city { int x, number; }c[maxn]; int id[maxn]; int pre[maxn]; int minv[maxn<<2]; int n, m, p, v; int ql, qr; void init(void) { memset(minv, 0, sizeof minv); memset(pre, -1, sizeof pre); } int cmp(city a, city b) { return a.xb) swap(a, b); pre[b]=max(pre[b], a); } } void updata(int o, int L, int R) { if(L==R){ minv[o]=v; return; } int mid=(R+L)>>1; if(p<=mid) updata(lson); else updata(rson); minv[o]=min(minv[o<<1], minv[o<<1 | 1]); } int query(int o, int L, int R) { if(ql<=L && qr>=R) return minv[o]; int mid=(R+L)>>1, ans=INF; if(ql<=mid) ans=min(ans, query(lson)); if(qr>mid) ans=min(ans, query(rson)); return ans; } void solve(void) { int limit=0, dp=0; for(int i=1;i<=n;i++){ if(pre[i]!=-1) limit=max(pre[i], limit); ql=limit, qr=i-1; if(ql>=1 && qr>=1) dp=query(1, 1, n); p=i, v=dp+c[i+1].x-c[i].x; updata(1, 1, n); } printf("%d\n", dp); } int main(void) { while(scanf("%d%d",&n,&m)!=EOF){ init(); work(); solve(); } return 0; }