寫在前面:html
我發現我每一次寫題解都是改題改不出來了QAQios
其實今天的題都還好啦。
數組
其實就是 luogu儀仗隊 的數據擴大版,開個long long而後數組開大點就能夠過了。ide
這個題就頗有意思了。函數
小W和他的東廠廠長叔叔去打窗戶。。。。spa
其中兩句話頗有誤導的含義,很多人都死在了這句話上面。【其實只有我 /滑稽code
每秒只能完全打破一扇窗戶。 htm
你不能要求他們叔侄兩個打破不一樣的窗戶得到的快樂值必須相同。blog
錯誤的貪心策略:排序
把全部的窗戶按時間排序,時間相同按價值排序,而後模擬選擇。
實際上,很容易就能發現錯誤,好比下面這組數據:
3
1 10
2 20
2 20
正確答案顯然是40,可是上面這個作法卻會使得答案變成30.
問題就出在單位決策。
那麼怎麼作呢?
爲了防止重複,咱們先把時間從大到小排序,那麼顯然在主人先回來的窗戶前面的窗能夠在這以前的任什麼時候間裏打破。
注意每次都要判斷價值是否爲負數,若是是非負數的話,那麼咱們就把這個點壓入堆中,而後在它距離下一個時間點的時間裏,咱們能夠在堆中取啊a[i].t-1-a[i+1].t個點,這些點就是最優策略。
代碼放上:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #define ll long long using namespace std; const int maxn=200007; int n; struct ss{ int tim,val; bool operator < (const ss &b) const{ if(tim==b.tim) return val>b.val; return tim>b.tim; } }win[maxn]; priority_queue<int> q; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&win[i].tim,&win[i].val); sort(win+1,win+n+1); ll ans=0; for(int i=1;i<=n;i++) { if(win[i].val<0) continue; q.push(win[i].val); for(int j=win[i+1].tim;j<=win[i].tim-1&&!q.empty();j++) { ans+=q.top(); q.pop(); } } cout<<ans<<endl; return 0; }
敬告啊敬告,考試的時候必定不要忘乎所以QAQ
本題有兩種作法,環套樹DP以及貪心。
貪心相對來講,比較好想出來。
隨便畫上幾張比較正常的圖來看,很容易發現,全部入度爲0的點是確定不能投放的。
那麼這些節點的兒子怎麼看呢?
能夠分紅兩部分來看:
1.環上。【爲何成環這種東西。。。顯然吧
2.環之間相連。
那麼,決策就顯而易見了,
爲了儘量投放更多的點,就把全部沒有受到環限制的全部2類型的邊所有投放。
對於環上的點,則是環大小 / 2.
同類的題還有 luogu消防局的設立
本題代碼放上
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; const int maxn=1e6+7; int n,ans; int a[maxn],in[maxn]; int choic[maxn]; queue<int> q; void px() { while(!q.empty()) { int x=q.front(); q.pop(); if(!choic[a[x]]) { choic[a[x]]=-1;//扔 if(!--in[a[a[x]]]) { choic[a[a[x]]]=1; q.push(a[a[x]]); } } } return; } int get_h(int x,int cnt) { while(!choic[x]) { cnt++; choic[x]=2;//環上 x=a[x]; } return cnt/2; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); in[a[i]]++; } for(int i=1;i<=n;i++) { if(!in[i]) { choic[i]=1;//要保留 q.push(i); } } px(); for(int i=1;i<=n;i++) { if(choic[i]) continue; ans+=get_h(i,0); } for(int i=1;i<=n;i++) { if(choic[i]==-1) ans++; } cout<<ans<<endl; return 0; }
關於基環樹,點這裏。
關於代碼。。。
我鴿了。。。
小結一下吧,今天的考試本應該能差很少的QAQ
可是因爲longlong,數組什麼的問題 t1 和 t2 直接折半QAQ
還有遞歸函數不熟練的最好不要不要傳參,否則傳的傳的傳出來的可能就不是你想要的了QAQ
最後但願你們CSP RP++++++++++++