hdu 2430 Beans
阿新 • • 發佈:2019-02-15
題意:題目大意:有n坨豌豆,每坨都有w[i]個,現在要從中選擇連續的若干坨,然後用一個能裝p個豌豆的揹包裝豆子,直到剩下的豌豆數量<=p為止,還要求剩下的豌豆數量少於k,問最多能裝多少包。-------引自ZeroClock
題解:
1.目標是求(sum[i] - sum[j](i != j)) % p <= k && 使得sum[i] - sum[j]最大
2.變形-----(sum[i] % p - sum[j] % p + p) % p <= k
3.然後我們可以按sum[i] % p,給陣列排序。
4.用單調佇列分情況討論解決這個問題了
5.hint:因為存在某堆有0個bean的情況,需要在排序的時候特殊處理
總結:
1.這道題又是看到zeroclock說需要把式子變形之後才知道怎麼寫的。
2.當沒有方向的時候,應該嘗試著對公式進行小小的變形,貌似在這種地方栽過好幾次跟頭了
3.最近依舊學習opencv,幾乎把書從頭到尾的讀了一遍,發現確實應該抓住重點看書,看急需瞭解的知識,對於不會
的需要延伸的知識,再去有目的的查資料,這樣效率更高!
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; #define MAXN 1000005 int n,p,k; struct Node { ll s; bool operator < (const Node & a)const{ if(s % p == a.s % p)return s < a.s; return s % p < a.s % p; } }node[MAXN]; ll deque[MAXN]; int main() { int _; for(int kcas = scanf("%d",&_);kcas <= _;kcas++) { scanf("%d%d%d",&n,&p,&k); bool success = false; for(int i = 1;i <= n;i++) { scanf("%I64d",&node[i].s); if(node[i].s == 0)success = true; node[i].s += node[i - 1].s; } sort(node,node + n + 1); ll maxn = 0,ans = 0; int tail = 0,head = 0; for(int i = 1,j = 0;i <= n;i++) { while(tail != head && deque[tail - 1] > node[i - 1].s) tail--; deque[tail++] = node[i - 1].s; while(tail != head && deque[head] % p + k < node[i].s % p) head++; if(head != tail)ans = max(ans,node[i].s - deque[head]); while(j < i && node[j].s % p + p - node[i].s % p <= k) { maxn = max(maxn,node[j].s); j++; } ans = max(ans,maxn - node[i].s); } if(!ans && !success)printf("Case %d: -1\n",kcas); else printf("Case %d: %I64d\n",kcas,ans / p); } }