日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jzoj1295,P1607-轻轨(庙会班车)【贪心,线段树】

發布時間:2023/12/3 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj1295,P1607-轻轨(庙会班车)【贪心,线段树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

我考試時敲了一個不僅比正解編程復雜度高,而且時間更慢,還AC不了的費用流

垃圾代碼

#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define MN 20011 using namespace std; struct node{int to,w,next,c; }a[150001]; queue<int> q; int tot,k,n,c,s,e,x,y,w,sum; int ls[MN],maxf[MN],b[MN],f[MN],v[MN]; void addl(int x,int y,int w,int c) {a[++tot].to=y;a[tot].w=w;a[tot].next=ls[x];ls[x]=tot;a[tot].c=c;a[++tot].to=x;a[tot].w=0;a[tot].next=ls[y];ls[y]=tot;a[tot].c=-c; } bool spfa() {memset(f,-127/3,sizeof(f));while (!q.empty()) q.pop();q.push(s);v[s]=true;f[s]=0;maxf[s]=2147483647;while (!q.empty()){int x=q.front();v[x]=false;q.pop();for (int i=ls[x];i;i=a[i].next){int y=a[i].to;if (a[i].w&&f[x]+a[i].c>f[y]){f[y]=f[x]+a[i].c;maxf[y]=min(maxf[x],a[i].w);b[y]=i;if (!v[y]){q.push(y);v[y]=true;}}}}if (f[e]>-690563370) return true;else return false; } int updata() {x=e;int ans=0;while (x!=s){a[b[x]].w-=maxf[e];a[b[x]^1].w+=maxf[e];ans+=a[b[x]].c;x=a[b[x]^1].to;}return ans*maxf[e]; } int main() {tot=1;scanf("%d%d%d",&k,&n,&c);s=n+1;e=s+1;addl(s,1,c,0);addl(n,e,c,0);for (int i=1;i<n;i++) addl(i,i+1,c,0);for (int i=1;i<=k;i++){scanf("%d%d%d",&x,&y,&w);addl(x,y,w,1);}while (spfa()) sum+=updata();printf("%d",sum); } //If you want to AK(IOI)! //first: // AK | AK IOI //sto orz|sto orz //sto orz|sto orz //sto xjq orz|sto hzb orz //sto orz|sto orz //sto orz|sto orz //Then you will AK(IOI)! //不要問我為啥會有上面的東西

大意

一個列車可以坐CC頭牛,有KK組牛,每組mimi個,從sisi出發到eiei。求最多可以帶多少頭牛。


解題思路

首先眾所周知可以用數學歸納法證明每次選取結束時間最早的是最優解
自己理解的證明:
選結束時間晚的只有兩種情況

1.

這種情況綠色比紅色占的范圍更大,肯定不一定最優解。


2.

這種情況由于被紅色線段占了的已經計算過了,如果計算紅色的話那么前面的一定沒有被紅色覆蓋,所以按照這么算其實就是這樣

這樣的話綠色占的范圍依舊比紅色大,所以依舊不一定是最優解。

好了,證明完了之后就可以先按照結束位置排個序,用(i,i)(i,i)這個區間來表示在ii<script type="math/tex" id="MathJax-Element-238">i</script>這個時間點車子計算到現在空閑的容量,然后枚舉將每個開始到結束區間盡量減到0(能減就減,當然注意這個組的人數)


代碼

#include<cstdio> #include<algorithm> using namespace std; struct node{int star,end,w; }w[50001]; struct treenode{int l,r,w,lazy; }a[80001]; int k,n,c,s; void build(int x,int l,int r,int num) {a[x].l=l;a[x].r=r;a[x].w=num;if (l==r) return;int mid=(l+r)/2;build(x*2,l,mid,num);build(x*2+1,mid+1,r,num); } void ddata(int x) {if (a[x].lazy){a[x*2].w+=a[x].lazy;a[x*2+1].w+=a[x].lazy;a[x*2].lazy+=a[x].lazy;a[x*2+1].lazy+=a[x].lazy;a[x].lazy=0;} } void updata(int x,int l,int r,int num) {if (a[x].l==l&&a[x].r==r){a[x].w+=num;a[x].lazy+=num;return;}ddata(x);if (a[x*2].r>=r) updata(x*2,l,r,num);else if (a[x*2+1].l<=l) updata(x*2+1,l,r,num);else updata(x*2,l,a[x*2].r,num),updata(x*2+1,a[x*2+1].l,r,num);a[x].w=min(a[x*2].w,a[x*2+1].w); } int find(int x,int l,int r) {if (a[x].l==l&&a[x].r==r)return a[x].w;ddata(x);if (a[x*2].r>=r) return find(x*2,l,r);else if (a[x*2+1].l<=l) return find(x*2+1,l,r);else{ a[x].w=min(a[x*2].w,a[x*2+1].w);return min(find(x*2,l,a[x*2].r),find(x*2+1,a[x*2+1].l,r));} } bool cmp(node x,node y) {return x.end<y.end; } int main() {scanf("%d%d%d",&k,&n,&c); for (int i=1;i<=k;i++){scanf("%d%d%d",&w[i].star,&w[i].end,&w[i].w);}build(1,1,n,c);//建樹sort(w+1,w+1+k,cmp);//排序for (int i=1;i<=k;i++){int h=find(1,w[i].star,w[i].end-1);if (h)//是否可以接牛{updata(1,w[i].star,w[i].end-1,-min(h,w[i].w));//修改區間s+=min(h,w[i].w);//累計答案}}printf("%d",s); }

總結

以上是生活随笔為你收集整理的jzoj1295,P1607-轻轨(庙会班车)【贪心,线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。