[HNOI2005]狡猾的商人 ,神奇做法——貪心
阿新 • • 發佈:2018-03-25
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]狡猾的商人 ,神奇做法——貪心