首页 > 代码库 > [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 }
[SRM] 09 撕书狂魔CZL
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。