【线段树dp】115E - Linear Kingdom Races
http://codeforces.com/problemset/problem/115/E
题目大意,给你1~n段路,每段路修好需要一定代价,同时给m个区间,如果连续修好li~ri的所有路就可以获得pi的收益,询问最大利润。
想了一会,发现除了暴力的dp没有其他办法,但是10^5级别让n^2的dp无能为力,后来看到题目旁边datastruct+dp的提示,想到用线段树来优化dp的方法。
k表示当前区间,dp[i]:表示从第i段路修到当前路段全部修好的最大收益。
如果某一个比赛区间[Li,Ri]右端点刚好为当前区间,则显然dp[1]~dp[Li] 全部要加上pi;
再考虑当前区间移到下一个区间时候,dp[k+1]=当前最优解-cost[k+1], 同时dp[1]~dp[k]都需要减掉cost[k+1].
最后考虑更新当前最优解,ans = max( ans , dp[1],dp[2]...dp[k] );
到此,发现dp所有操作均能用线段树优化成O(logn)...
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 200005 6 using namespace std; 7 typedef long long LL; 8 9 struct Node{ 10 int left ,right; 11 LL key,ma; 12 }tree[maxn*4]; 13 void build(int left ,int right ,int step ) { 14 tree[step].left = left; tree[step].right = right; 15 if ( left == right ) return; 16 int mid = ( left + right)/2; 17 build( left , mid , step*2 ); 18 build(mid+1 ,right, step*2+1 ); 19 } 20 void down(int step ) { 21 if ( tree[step].key == 0 ) return; 22 LL key = tree[step].key; 23 tree[step].key = 0; 24 tree[step*2].key += key; 25 tree[step*2].ma += key; 26 tree[step*2+1].key += key; 27 tree[step*2+1].ma += key; 28 } 29 void updata(int left , int right , LL key , int step ) { 30 if ( tree[step].left == left && tree[step].right == right ) { 31 tree[step].key += key; 32 tree[step].ma += key; 33 return; 34 } 35 down(step); 36 int mid = ( tree[step].left + tree[step].right )/2; 37 if ( right <= mid ) updata( left,right,key, step*2 ); 38 else if ( left > mid ) updata( left,right,key,step*2+1 ); 39 else { 40 updata( left , mid , key , step*2 ); 41 updata(mid+1 ,right, key , step*2+1 ); 42 } 43 tree[step].ma = max( tree[step*2].ma , tree[step*2+1].ma ); 44 } 45 LL ask( int left ,int right , int step ) { 46 if ( tree[step].left == left && tree[step].right == right ) return tree[step].ma; 47 down( step ); 48 int mid = ( tree[step].left + tree[step].right )/2; 49 if ( right <= mid ) return ask(left,right,step*2); 50 else if ( left > mid ) return ask(left,right,step*2+1); 51 else return max(ask(left,mid,step*2),ask(mid+1,right,step*2+1)); 52 } 53 54 int n,m,c[maxn]; 55 struct node{ 56 int l , r , p; 57 }data[maxn]; 58 bool cmp( const node &a , const node &b ) { 59 return a.r < b.r; 60 } 61 int main(){ 62 scanf("%d%d", &n, &m ); 63 for (int i = 1; i<=n; i++) scanf("%d", &c[i] ); 64 for (int i = 0; i<m; i++) scanf("%d%d%d", &data[i].l, &data[i].r, &data[i].p ); 65 sort( data , data+m , cmp ); 66 build(0,n,1); 67 LL ans = 0; 68 for (int i = 1,k=0; i<=n; i++ ) { 69 updata(i,i,ans,1); 70 updata(1,i,-c[i],1); 71 while ( k<m && data[k].r == i ) { 72 updata(1,data[k].l,data[k].p,1); 73 k++; 74 } 75 ans = max( ans , ask(1,n,1) ); 76 // printf("%d %d:" , i , k ); 77 // for (int j = 1; j<=i; j++) printf("%lld ", ask(j,j,1) ); puts(""); 78 } 79 printf("%lld\n" , ans ); 80 return 0; 81 }