传送门:区间
思路:
首先就是要找不等式关系
这里使用前缀和的思想对题目里面的关系进行分析。
设前缀和数组s[i],表示前i个数里面被选出来的数的个数,因为数据的范围时0~50000,所以可以将每个数都放大1个位变成1~50001。因为题目要求的是尽量少的数,所以要用最长路来求。
有s[0]=0;
由前缀和的性质可得出以下的关系式
1.s[i]>=s[i-1] add(i-1,i,0);
2.s[i]-s[i-1]<=1 ==> s[i-1]>= s[i]-1 add(i,i-1,-1);
3.对于给出的区间[a,b]都必须有s[b]-s[a-1]>=c add(a-1,b,c);
这里因为一定有答案,所以不用栈。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
int n,m;
const int N=1e5+10,M=3e5+10;
int e[M],ne[M],h[N],w[M],idx;
ll dist[N];
bool st[N];
int q[N];
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
bool spfa()
{
int hh=0,tt=1;
memset(dist,-0x3f,sizeof dist);
dist[0]=0;
st[0]=true;
while(hh!=tt)
{
int t=q[hh++];
if(hh==N) hh=0;
st[t]=false;
for(int i=h[t];~i;i=ne[i])
{
int j=e[i];
if(dist[j]<dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
if(!st[j])
{
q[tt++]=j;
if(tt==N) tt=0;
st[j]=true;
}
}
}
}
return true;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d",&n);
for(int i=1;i<=50001;i++)
{
add(i-1,i,0);
add(i,i-1,-1);
}
while(n--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
a++,b++;
add(a-1,b,c);
}
spfa();
printf("%lld",dist[50001]);
return 0;
}