COJ 0343 WZJ的公司(二)

传送门: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
",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
",adj[i].x,adj[i].y,adj[i].w);
50     //for(int i=1;i<=n+1;i++) printf("dist[%d]=%d
",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('
');
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
",f[n]);
54     return 0;
55 }
原文地址:https://www.cnblogs.com/chxer/p/4445508.html