1. 程式人生 > >[HNOI2005]狡猾的商人 ,神奇做法——貪心

[HNOI2005]狡猾的商人 ,神奇做法——貪心

fine oid sdi git 隊列實現 operator read ++ log

洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法——貪心

  • 看到大牛都是寫的差分約束或帶權並查集,本蒟蒻都不太會(還是用差分約束過了的QAQ),但是想出一種貪心的策略,運用神奇的優先隊列實現。

  • 思路是:先按左端點為第一排序關鍵字,再排右端點。之後就開始兩兩比較,如果左端點相等,就比較右端點,如果相等,就比較值,如果值不同,就直接輸出false,否則輸出true,如果右端點不等,就把相同的部分抵消掉,把新的區間再壓入優先隊列。直到不能操作,就輸出true。

下附代碼:

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring> #include<iostream> #include<algorithm> #define N 1100 using namespace std; inline void read(int &x) { x=0; int p=1; char c=getchar(); while(!isdigit(c)){if(c==‘-‘)p=-1;c=getchar();} while(isdigit(c)) {x=(x<<1)+(x<<3)+(c^‘0‘);c=getchar();} x*=p; }//快速讀入
int n,m; struct node { int l,r,s; bool operator < (const node &h)const { if(l!=h.l)return l>h.l; return r>h.r; }//重載運算符,確定優先隊列的優先級 }tmp; priority_queue<node>q; int main() { int t; read(t); while(t--) { while (!q.empty()) q.pop();//多組數據清空
read(n);read(m); if(m==1){printf("true\n");continue;}//其實沒必要特判,只是優化一點點 for(int i=1;i<=m;i++) { int l,r,s; read(tmp.l);read(tmp.r);read(tmp.s); q.push(tmp); } tmp=q.top();//取出第一個 q.pop(); while(!q.empty()) { node tmp1; tmp1=q.top(); q.pop(); if(tmp.l==tmp1.l) { if(tmp.r==tmp1.r) { if(tmp.s!=tmp1.s) {printf("false\n");goto end;}//退出多重循環的小操作 } else if(tmp.r<tmp1.r) q.push((node) {tmp.r+1, tmp1.r, tmp1.s - tmp.s});//將抵消後的部分放入隊列 } tmp = tmp1;//繼續比 } printf("true\n"); end:; } return 0; }

[HNOI2005]狡猾的商人 ,神奇做法——貪心