题目描述
输入输出格式
输入格式:
从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断。每组数据的第一行为两个正整数n和m,其中n < 100,m < 1000,分别表示对应的账本记录了多少个月的收入情况以及偷看了多少次账本。接下来的m行表示刁姹偷看m次账本后记住的m条信息,每条信息占一行,有三个整数s,t和v,表示从第s个月到第t个月(包含第t个月)的总收入为v,这里假设s总是小于等于t。
输出格式:
输出文件output.txt中包含w行,每行是true或false,其中第i行为true当且仅当第i组数据,即第i个账本不是假的;第i行为false当且仅当第i组数据,即第i个账本是假的。
输入输出样例
输入样例#1: 复制
2 3 3 1 2 10 1 3 -5 3 3 -15 5 3 1 5 100 3 5 50 1 2 51
输出样例#1: 复制
true false
一看不难想到f[s]-f[t]=v可以用差分约束f[s]-f[t]<=v和f[t]-f[s]<=v,然后常规操作。
考虑一种贪心算法。
对于已知的一段时间(l,r),如果有sum[l,r]和已知的v[l,r]不同,显然false。
对于已知sum[l,r]和sum[l,m]可以推出[m,r],所以可以用优先队列解决。
AC代码如下:
#include<cstdio> #include<algorithm> #include<queue> using namespace std; struct p { int l,r,sum; bool operator <(const p &a) const { if(a.l==l) return r>a.r; return l>a.l;} }x,y; priority_queue<p>q; int T,n,m; bool ans; int main() { scanf("%d",&T); while(T--) { ans=0; while(!q.empty()) q.pop(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&x.l,&x.r,&x.sum),q.push(x); x=q.top(); q.pop(); while(!q.empty()) { y=q.top(); q.pop(); if(x.l==y.l&&x.r==y.r&&x.sum!=y.sum) {ans=1;break;} if(x.l==y.l&&x.r<y.r) q.push((p){x.r+1,y.r,y.sum-x.sum}); x=y; } if(ans) printf("false\n"); else printf("true\n"); } return 0; }