题意:有一个数组 S,现给定 m 次查询,每次给出两种形式的数据:
① x y gt k:代表 S[x]+S[x+1]+...+S[x+y]>k;
② x y lt k:代表 S[x]+S[x+1]+...+S[x+y]<k;
现在问存不存在这样的数组 S ,满足所有的查询;
分析:我们设 sum[i] 表示 s[1]~s[i] 的和,则
① S[x]+S[x+1]+...+S[x+y]>k ----> sum[x+y]-sum[x-1]>k;
② S[x]+S[x+1]+...+S[x+y]<k ----> sum[x+y]-sum[x-1]<k;
我们设 a=x-1,b=x+y,则有相应的转化
① sum[b]-sum[a]>k;
② sum[b]-sum[a]<k;
问题转化成了存不存在这样的sum数组满足所有的查询,根据上述不等式很容易可以想到差分约束,因为差分要求带上等号,所以稍微转化一下:
1)sum[b]-sum[a]<k ---- sum[b]-sum[a]>=k+1 ---- sum[a]-sum[b]<=-k-1 ;
2)sum[b]-sum[a]<k ---- sum[b]-sum[a]<=k- 1 ;
这样就满足差分约束求最小值的条件,然后用SPFA判环就可以了,注意可能所有查询构成的图不连通,所以得加0做超级源点;
代码:
#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;
const int INF = 1E9+7;
const int N = 1E5+10;
struct node{
int to,w,nxt;
}e[N];
int head[N],tot,n,m;
bool vis[N];
int dis[N],out[N];
void add(int u,int v,int w){
e[tot].to=v;
e[tot].w=w;
e[tot].nxt=head[u];
head[u]=tot++;
}
void init(){
tot=0;
for(int i=0;i<=n;i++){
head[i]=-1;
dis[i]=INF;
out[i]=0;
}
}
void input(){
scanf("%d",&m);
while(m--){
int x,y,k; char op[3];
scanf("%d%d%s%d",&x,&y,op,&k);
int a=x-1,b=x+y;
if(op[0]=='g') add(b,a,-k-1);
else add(a,b,k-1);
}
}
bool SPFA(){
queue<int>q;
for(int i=0;i<=n;i++) q.push(i),vis[i]=1;
while(!q.empty()){
int u=q.front(); q.pop();
vis[u]=0;
if(++out[u]>n+1) return false;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
return true;
}
int main()
{
while(~scanf("%d",&n)&&n){
init();
input();
if(SPFA()) puts("lamentable kingdom");
else puts("successful conspiracy");
}
}