差分约束裸题
根据题意建立相应的图
设s[k]表示0~k中最少取多少个整数,根据题意可知
s[bi]-s[ai-1]>=ci
还有一些隐含条件
s[k]-s[k-1]>=0. 0~k之间选出来的数肯定不必0~k-1少
s[k]-s[k-1]<=1. 每个数只能被选一次,可变形
最后求单源最长路
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int m=500020; 8 const int inf=0x3f3f3f3f; 9 int head[m], dis[m]; 10 bool vis[m]; 11 int maxn, minn; 12 int T, n; 13 int cnt; 14 struct Edge{ 15 int to, w, next; 16 }e[m*4]; 17 void add(int u,int v,int w){ 18 cnt++; 19 e[cnt].next=head[u]; 20 e[cnt].w=w; 21 e[cnt].to=v; 22 head[u]=cnt; 23 } 24 int spfa(int s){ 25 queue<int> q; 26 int top=0; 27 for(int i=minn; i<=maxn; i++){ 28 dis[i]=-inf; 29 } 30 dis[s]=0; 31 memset(vis, false, sizeof(vis)); 32 q.push(s); 33 vis[s]=true; 34 while(!q.empty()){ 35 int u=q.front(); 36 q.pop(); 37 vis[u]=false; 38 for(int i=head[u]; i!=-1; i=e[i].next){ 39 int v=e[i].to; 40 int w=e[i].w; 41 if(dis[v]<dis[u]+w){ 42 dis[v]=dis[u]+w; 43 if(!vis[v]){ 44 q.push(v); 45 vis[v]=true; 46 } 47 } 48 } 49 } 50 return dis[maxn]; 51 } 52 int main(){ 53 scanf("%d",&T); 54 while(T--){ 55 scanf("%d",&n); 56 int a, b, c; 57 memset(head,-1,sizeof(head)); 58 minn=inf; 59 maxn=0; 60 for(int i=1; i<=n; i++){ 61 scanf("%d%d%d",&a,&b,&c); 62 add(a-1, b, c); 63 maxn=max(maxn,b); 64 minn=min(minn,a-1); 65 } 66 for(int i=minn; i<=maxn; i++){ 67 add(i, i+1, 0); 68 add(i+1, i, -1); 69 } 70 int ans=spfa(minn); 71 printf("%d ",ans); 72 if(T) printf(" "); 73 } 74 return 0; 75 }