首页 > 代码库 > [SRM] 09 撕书狂魔CZL

[SRM] 09 撕书狂魔CZL

A. 撕书Ⅰ

序列型DP。DP[i]表示当前编号结点的撕书页数。

那么我们有 DP[ i ] = DP[ i - y - 1 ] + y

其中y为编号i书页对应范围内的书页。

那么,具体实现的话,需要求出每个i对应的y,这里用前缀和。

技术分享
 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define maxn 1000005 5 #define lowbit(x) (-x&x) 6 using namespace std; 7  8 int n,high = 0; 9 10 struct node{11     int pos,ai;12 }list[maxn];13 14 int Tree[maxn],DP[maxn],minn;15 int sum(int p){16     int ans = 0;17     while(p){18 //        cout << ‘^‘;19 //        cout << p;20         ans += Tree[p];21         p -= lowbit(p);22     }23     return ans;24 }25 void add(int p){26     while(p <= high){27 //        cout << ‘G‘;28         Tree[p]++;29         p += lowbit(p);30 //        cout << p;31     }32 }33 34 bool cmp(const node &a,const node &b){35     return a.pos < b.pos;36 }37 38 int main(){39     scanf("%d",&n);40     41     for(int i = 1;i <= n;i++){42         scanf("%d%d",&list[i].pos,&list[i].ai);43         list[i].pos++;44         high = max(high,list[i].pos);45     }46     47     sort(list+1,list+1+n,cmp);48     49 //    printf("#%d#\n",high);50     51     for(int i = 1;i <= n;i++){52         53 //        cout << ‘A‘;54         add(list[i].pos);55     }56     57     for(int i = 1;i <= n;i++){58         int a = list[i].pos-1;59         int b = list[i].pos-list[i].ai-1;60         if(a < 0) a = 0;61         if(b < 0) b = 0;62         int y = sum(a)-sum(b);63         if(i-y-1 < 0) continue;64         DP[i] = DP[i-y-1] + y;65     }66     67     minn = DP[n];68     69     for(int i = 1;i <= n;i++){70         minn = min(minn,DP[i]+n-i);71     }72     73     printf("%d",minn);74     75 //    cout << endl;76 //    for(int i = 0;i <= n;i++) printf("%d ",DP[i]);77     78 //    cout << endl;79 //    for(int i = 0;i <= 10;i++) printf("%d ",sum(i));80     81     return 0;82 }
震惊!CYC的背景居然隐藏着这样的...

 

[SRM] 09 撕书狂魔CZL