L3-2 森森快递 (30 分)(贪心+线段树/分块)

题目链接:https://pintia.cn/problem-sets/1108203702759940096/problems/1108204121661857798

题目大意:

森森开了一家快递公司,叫森森快递。因为公司刚刚开张,所以业务路线很简单,可以认为是一条直线上的N个城市,这些城市从左到右依次从0到(编号。由于道路限制,第i号城市(,)与第(号城市中间往返的运输货物重量在同一时刻不能超过Ci​​公斤。

公司开张后很快接到了Q张订单,其中j张订单描述了某些指定的货物要从Sj​​号城市运输到Tj​​号城市。这里我们简单地假设所有货物都有无限货源,森森会不定时地挑选其中一部分货物进行运输。安全起见,这些货物不会在中途卸货。

为了让公司整体效益更佳,森森想知道如何安排订单的运输,能使得运输的货物重量最大且符合道路的限制?要注意的是,发货时间有可能是任何时刻,所以我们安排订单的时候,必须保证共用同一条道路的所有货车的总重量不超载。例如我们安排1号城市到4号城市以及2号城市到4号城市两张订单的运输,则这两张订单的运输同时受2-3以及3-4两条道路的限制,因为两张订单的货物可能会同时在这些道路上运输。

具体思路:首先对区间的右端点进行排序,先处理短的区间,再去处理长的区间,这样就能保证是最大了。其实就是区间查询和区间修改。

 

作死用分块打的区间查询和区间修改,有一个两分的样例就是A不了。。以后这种区间修改还是用线段树吧,,

分块代码:

  1 #include
  2 using namespace std;
  3 # define ll long long
  4 const ll inf =0x3f3f3f3f3f3f3f3f;
  5 const int maxn= 3e6+100;
  6 ll a[maxn];
  7 struct node
  8 {
  9     ll st;
 10     ll ed;
 11     bool friend operator < (node t1,node t2)
 12     {
 13         return t1.ed<t2.ed;
 14     }
 15 } q[maxn];
 16 ll vis[maxn];
 17 ll belong[maxn];
 18 ll l[maxn],r[maxn];
 19 ll  add[maxn];
 20 ll sum[maxn];
 21 ll  n,m;
 22 void build()
 23 {
 24     ll block=(ll)sqrt(n-1ll);
 25     for(ll i=1; i)
 26         belong[i]=i/block+1ll;
 27     ll tot=(n-1)/block;
 28     if((n-1)%block)
 29         tot++;
 30     for(ll i=1; i<=tot; i++)
 31     {
 32         l[i]=(i-1)*block+1ll;
 33         r[i]=(i)*block;
 34     }
 35     r[tot]=n-1;
 36     for(ll i=1; i<=tot; i++)
 37     {
 38         sum[i]=inf;
 39         for(ll  j=l[i]; j<=r[i]; j++)
 40         {
 41             sum[i]=min(vis[j],sum[i]);
 42         }
 43     }
 44 }
 45 ll ask(ll st,ll ed)
 46 {
 47     ll ans=inf;
 48     if(belong[st]==belong[ed])
 49     {
 50         for(ll i=st; i<=ed; i++)
 51         {
 52             ans=min(ans,vis[i]+add[belong[st]]);
 53         }
 54         return ans;
 55     }
 56     for(ll i=st; i<=r[belong[st]]; i++)
 57         ans=min(ans,vis[i]+add[belong[st]]);
 58     for(ll i=l[belong[ed]]; i<=ed; i++)
 59         ans=min(ans,vis[i]+add[belong[ed]]);
 60     for(ll i=belong[st]+1; i)
 61         ans=min(ans,sum[i]+add[i]);
 62     return ans;
 63 }
 64 void  up(ll st,ll ed,ll val)
 65 {
 66     if(belong[st]==belong[ed])
 67     {
 68         for(ll i=st; i<=ed; i++)
 69         {
 70             vis[i]+=val;
 71             sum[belong[st]]=min(sum[belong[st]],vis[i]);
 72         }
 73         return ;
 74     }
 75     for(ll i=st; i<=r[belong[st]]; i++)
 76     {
 77         vis[i]+=val;
 78         sum[belong[st]]=min(sum[belong[st]],vis[i]);
 79     }
 80     for(ll i=l[belong[ed]]; i<=ed; i++)
 81     {
 82         vis[i]+=val;
 83         sum[belong[ed]]=min(sum[belong[ed]],vis[i]);
 84     }
 85     for(ll i=belong[st]+1; i)
 86     {
 87         add[i]+=val;
 88     }
 89 }
 90 signed  main()
 91 {
 92     // cout<
 93     scanf("%lld %lld",&n,&m);
 94     for(ll i=1; i)
 95         scanf("%lld",&vis[i]);
 96     sort(q+1,q+m+1);
 97     build();
 98     ll st,ed;
 99     for(ll i=1; i<=m; i++)
100     {
101         scanf("%lld %lld",&q[i].st,&q[i].ed);
102         q[i].st++;
103         q[i].ed++;
104         if (q[i].st > q[i].ed)
105             swap(q[i].st, q[i].ed);
106     }
107     sort(q+1,q+m+1);
108     ll sum=0;
109     for(ll i=1; i<=m; i++)
110     {
111         ll minn;
112         minn=ask(q[i].st,q[i].ed-1);
113         sum+=minn;
114         up(q[i].st,q[i].ed-1,-minn);
115     }
116     printf("%lld\n",sum);
117     return 0;
118 }
View Code

线段树代码:

 1 #include
 2 using namespace std;
 3 # define ll long long
 4 # define lson l,m,rt<<1
 5 # define rson m,r,rt<<1|1
 6 const ll inf =0x3f3f3f3f3f3f3f;
 7 const int maxn= 3e6+100;
 8 struct node
 9 {
10     ll st;
11     ll ed;
12     bool friend operator < (node t1,node t2)
13     {
14         return t1.ed<t2.ed;
15     }
16 } q[maxn];
17 ll tree[maxn<<2],lazy[maxn<<2];
18 void up(ll rt)
19 {
20     tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
21 }
22 void down(int rt)
23 {
24     tree[rt<<1]+=lazy[rt];
25     tree[rt<<1|1]+=lazy[rt];
26     lazy[rt<<1]+=lazy[rt];
27     lazy[rt<<1|1]+=lazy[rt];
28     lazy[rt]=0;
29 }
30 void build(ll l,ll r,ll rt)
31 {
32     if(l+1==r)
33     {
34         scanf("%lld",&tree[rt]);
35         return ;
36     }
37     ll m=(l+r)>>1;
38     build(lson);
39     build(rson);
40     up(rt);
41 }
42 ll ask(ll L,ll R,ll l, ll r,ll rt)
43 {
44     if(R<=l||L>=r)
45         return inf ;
46     if(L<=l&&R>=r)
47     {
48         return tree[rt];
49     }
50     ll m=(l+r)>>1ll;
51     down(rt);
52     return min(ask(L,R,lson),ask(L,R,rson));
53 }
54 void  update(ll L,ll R,ll l,ll r,ll rt,ll val)
55 {
56     if(R<=l||L>=r)
57         return ;
58     if(L<=l&&R>=r)
59     {
60         tree[rt]+=val;
61         lazy[rt]+=val;
62         return ;
63     }
64     ll m=(l+r)>>1;
65     down(rt);
66     update(L,R,lson,val);
67     update(L,R,rson,val);
68     up(rt);
69 }
70 int  main()
71 {
72     ll n,m;
73     // cout<
74     scanf("%lld %lld",&n,&m);
75     build(1,n,1);
76     ll st,ed;
77     for(ll i=1; i<=m; i++)
78     {
79         scanf("%lld %lld",&q[i].st,&q[i].ed);
80         q[i].st++;
81         q[i].ed++;
82         if (q[i].st > q[i].ed)
83             swap(q[i].st, q[i].ed);
84     }
85     sort(q+1,q+m+1);
86     ll sum=0;
87     for(ll i=1; i<=m; i++)
88     {
89         ll minn;
90         minn=ask(q[i].st,q[i].ed,1,n,1);
91         sum+=minn;
92         update(q[i].st,q[i].ed,1,n,1,-minn);
93     }
94     printf("%lld\n",sum);
95     return 0;
96 }
View Code

 

转载于:https://www.cnblogs.com/letlifestop/p/10573088.html

你可能感兴趣的:(L3-2 森森快递 (30 分)(贪心+线段树/分块))