传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=313
试题描述:
WZJ的公司放假了!为了保证假期期间公司的安全,WZJ决定雇佣一些人来看守公司。有M个大学生来应聘,他们想要的工资是Ci元,可以为WZJ从第Si天到Ti天看守公司。WZJ是个决定在花钱前提下雇佣一些人,使得从第1天到第N天都至少有一个人看守公司,你能帮帮他吗(若无解输出"No Answer.")?
输入:
第一行为两个正整数N,M。
第二行至第M+1行第i+1行为3个正整数Si、Ti、Ci。
输出:
输出WZJ最少花的钱数(若无解输出"No Answer.")。
输入示例:
5 4
1 2 3
2 4 1
4 5 2
1 5 8
输出示例:
6
其他说明:
1<=N,M<=100000
1<=Si<=Ti<=N
1<=Ci<=2000
线段树练习题
题解:先想到将每一天抽象成点,来一个(L,R)的人就添一条边L->R+1权值为工资,然后跑一遍最短路貌似就搞定了
---------当然没搞定了啊,比如你让(1,6),(4,8)情何以堪啊,所以先搞一下所有的(i,i-1)权值为0的边就好了.
当然了,此题本来就是要用线段树瞎搞一个背包动规……
最短路:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int maxn=100000+10,INF=-1u>>1; 8 struct Tedge{int x,y,w,next;}adj[maxn*2];int fch[maxn],ms=0; 9 void AddEdge(int u,int v,int w){ 10 adj[++ms]=(Tedge){u,v,w,fch[u]};fch[u]=ms;return; 11 } 12 bool vis[maxn];int dist[maxn],n,m; 13 void SPFA(){ 14 queue<int>Q;memset(vis,false,sizeof(vis)); 15 for(int i=1;i<=n+1;i++)dist[i]=INF;dist[1]=0; 16 Q.push(1);vis[1]=true; 17 while(!Q.empty()){ 18 int u=Q.front();Q.pop();vis[u]=false; 19 for(int i=fch[u];i;i=adj[i].next){ 20 int v=adj[i].y; 21 if(dist[v]>dist[u]+adj[i].w){ 22 dist[v]=dist[u]+adj[i].w; 23 if(!vis[v]) vis[v]=true,Q.push(v); 24 } 25 } 26 } return ; 27 } 28 inline int read(){ 29 int x=0,sig=1;char ch=getchar(); 30 while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();} 31 while(isdigit(ch)) x=10*x+ch-'0',ch=getchar(); 32 return x*=sig; 33 } 34 inline void write(int x){ 35 if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x; 36 int len=0,buf[15];while(x) buf[len++]=x%10,x/=10; 37 for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return; 38 } 39 void init(){ 40 n=read();m=read();int a,b,c; 41 for(int i=n+1;i>1;i--) AddEdge(i,i-1,0); 42 for(int i=1;i<=m;i++){ 43 a=read();b=read();c=read(); 44 AddEdge(a,b+1,c);//printf("-AddEdge-%d %d %d\n",k,j,c); 45 } return; 46 } 47 void work(){ 48 SPFA(); 49 //for(int i=1;i<=ms;i++)printf("-Edge- %d to %d is %d\n",adj[i].x,adj[i].y,adj[i].w); 50 //for(int i=1;i<=n+1;i++) printf("dist[%d]=%d\n",i,dist[i]); 51 return; 52 } 53 void print(){ 54 if(dist[n+1]>=INF) puts("No Answer."); 55 else write(dist[n+1]),putchar('\n'); 56 return; 57 } 58 int main(){ 59 init();work();print();return 0; 60 } 61 /* 62 5 3 63 1 2 3 64 1 1 5 65 3 5 6 66 */
线段树:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=100010; 6 const int INF=1000000000; 7 int first[maxn],next[maxn],s[maxn],v[maxn],f[maxn]; 8 int minv[maxn*3],ql,qr,x,val; 9 void update(int o,int L,int R) 10 { 11 if(L==R) minv[o]=val; 12 else 13 { 14 int M=L+R>>1,lc=o<<1,rc=lc|1; 15 if(x<=M) update(lc,L,M); 16 else update(rc,M+1,R); 17 minv[o]=min(minv[lc],minv[rc]); 18 } 19 } 20 int query(int o,int L,int R) 21 { 22 if(ql<=L&&R<=qr) return minv[o]; 23 int M=L+R>>1,ans=INF,lc=o<<1,rc=lc|1; 24 if(ql<=M) ans=min(ans,query(lc,L,M)); 25 if(qr>M) ans=min(ans,query(rc,M+1,R)); 26 return ans; 27 } 28 int main() 29 { 30 int n,m,a,b,c; 31 scanf("%d%d",&n,&m); 32 for(int i=1;i<=m;i++) 33 { 34 scanf("%d%d%d",&a,&b,&c); 35 s[i]=a; v[i]=c; 36 next[i]=first[b]; 37 first[b]=i; 38 } 39 for(int i=1;i<=n*3;i++) minv[i]=INF; 40 update(1,0,n); 41 for(int i=1;i<=n;i++) 42 { 43 f[i]=INF; 44 for(int j=first[i];j;j=next[j]) 45 { 46 ql=s[j]-1;qr=i-1; 47 f[i]=min(f[i],v[j]+query(1,0,n)); 48 } 49 x=i; val=f[i]; 50 if(val!=INF) update(1,0,n); 51 } 52 if(f[n]==INF) puts("No Answer."); 53 else printf("%d\n",f[n]); 54 return 0; 55 }