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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

9.5题解

發(fā)布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 9.5题解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

總分201,rank3
T2圖上的簡單題,但調了好久,T3暴力分很足,st表加減枝91,T1嘛,卡讀題啊,QAQ……
先說坑爹的T1:
先是沒看見每種喜悅值只能獲得一次,改的時候又發(fā)現(xiàn)一次只可以買一個,233
狀壓每個狀態(tài)表示每種物品是否被買,轉移時可能轉移到自己或新的狀態(tài),導一下式子倒推就好了。

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<ctime> using namespace std; int n,bit[21]; long long all,v[21]; double p[21],pp,pll,now,f[1<<21]; int main(){bit[0]=1;for(int i=1;i<=20;i++)bit[i]=bit[i-1]<<1;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%lf%lld",&p[i],&v[i]);all+=v[i];pll+=p[i];}f[bit[n]-1]=0;for(int i=bit[n]-2;i>=0;i--){pp=0,now=0;for(int j=1;j<=n;j++){if(!(i&bit[j-1])){now+=p[j]*f[i|bit[j-1]];pp+=p[j];}}f[i]=(now+1.0)/(1.0*pp);}printf("%lld\n%0.3lf\n",all,f[0]); }

T2,就是縮點,然后貪心倒著找最小花費

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #define N 100050 #define M 200050 using namespace std; int head[2*N],e=1; struct edge{int u,v,w,next; }ed[2*M]; void add(int u,int v,int w){ed[e].u=u;ed[e].v=v;ed[e].w=w;ed[e].next=head[u];head[u]=e++; } int dfn[N],low[N],top,q[N],tot,id[N]; bool bo[N]; void tarjan(int x){dfn[x]=low[x]=++top;q[top]=x; bo[x]=1;for(int i=head[x];i;i=ed[i].next){int v=ed[i].v;if(!dfn[v]){tarjan(v);low[x]=min(low[x],low[v]);}else if(bo[v])low[x]=min(low[x],dfn[v]);}if(dfn[x]==low[x]){int y;tot++;do{y=q[top--];id[y]=tot;bo[y]=0;}while(y!=x);} } int n,m,ans,out[2*N]; bool vis[2*N]; queue<int> qu; void init(){e=1;ans=0;top=0;tot=n;memset(head,0,sizeof head);memset(dfn,0,sizeof dfn);memset(vis,0,sizeof vis);memset(bo,0,sizeof bo);memset(out,0,sizeof out); } int main(){while(scanf("%d%d",&n,&m)==2&&!(n==0&&m==0)){init();int u,v,w;for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);u++;v++;add(u,v,w);}for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);for(int i=1;i<=m;i++){int u=ed[i].u,v=ed[i].v;if(id[u]!=id[v]){add(id[v],id[u],ed[i].w);out[id[u]]++;}}for(int i=n+1;i<=tot;i++)if(!out[i]){qu.push(i);vis[i]=1;}while(!qu.empty()){int now=qu.front();qu.pop();int minn=0x7fffffff,nxt=-1;for(int i=head[now];i;i=ed[i].next){int v=ed[i].v; if(vis[v])continue;if(ed[i].w<minn){minn=ed[i].w;nxt=v;}}if(nxt==-1)break;for(int i=head[now];i;i=ed[i].next){if(vis[v])continue;out[ed[i].v]--;if(!out[ed[i].v]){qu.push(ed[i].v);vis[ed[i].v]=1;}}ans+=minn;}printf("%d\n",ans);}return 0; }

T3,考試暴力水了91
暴力

#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define N 50050 using namespace std; int n,a[N],maxn[N][20],minn[N][20],ans; void init(){for(int i=1;i<=n;i++)maxn[i][0]=a[i];for(int i=0;(1<<(i+1))<=n;i++)for(int j=1;(j+(1<<(i+1)))-1<=n;j++)maxn[j][i+1]=max(maxn[j][i],maxn[j+(1<<i)][i]);for(int i=1;i<=n;i++)minn[i][0]=a[i];for(int i=0;(1<<(i+1))<=n;i++)for(int j=1;(j+(1<<(i+1)))-1<=n;j++)minn[j][i+1]=min(minn[j][i],minn[j+(1<<i)][i]); } int work(int x,int y){int k=0;while((1<<(k+1))<y-x+1)k++;int dd=max(maxn[x][k],maxn[y-(1<<k)+1][k]);int xx=min(minn[x][k],minn[y-(1<<k)+1][k]);return dd-xx; } int main(){scanf("%d",&n);int x,y;for(int i=1;i<=n;i++){scanf("%d%d",&x,&y);a[x]=y;}init();for(int i=1;i<=n;i++){for(int j=i;j<=n;j++){int de=work(i,j);if(de<=j-i)ans++;else j=i+de-1;}}printf("%d\n",ans); }

正解分治,work(l,r)=work(l,mid)+work(mid+1,r)+跨過mid的,怎么算呢,分為四種情況搞,大小|,|大小,大|小,小|大。
根據(jù)max-min=r-l瞎搞就好了。

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #define N 300005 using namespace std; int maxl[N],maxr[N],minl[N],minr[N],b[4*N],a[N],n; int work(int l,int r){if(l==r)return 1;long long ans=0;int mid=(l+r)>>1;maxl[mid]=minl[mid]=a[mid];for(int i=mid-1;i>=l;i--){maxl[i]=max(maxl[i+1],a[i]);minl[i]=min(minl[i+1],a[i]);}maxr[mid+1]=minr[mid+1]=a[mid+1];for(int i=mid+2;i<=r;i++){maxr[i]=max(maxr[i-1],a[i]);minr[i]=min(minr[i-1],a[i]);}for(int i=mid;i>=l;i--){int d=i+maxl[i]-minl[i];if(d<=mid||d>r)continue;if(minr[d]>minl[i]&&maxr[d]<maxl[i])ans++;}for(int i=mid+1;i<=r;i++){int d=i-maxr[i]+minr[i];if(d>mid||d<l)continue;if(minl[d]>minr[i]&&maxl[d]<maxr[i])ans++;}int r1=mid+1,r2=mid;for(int i=mid;i>=l;i--){while(minr[r2+1]>minl[i]&&r2<r){r2++;b[maxr[r2]-r2+2*N]++;}while(maxr[r1]<maxl[i]&&r1<=r){b[maxr[r1]-r1+2*N]--;r1++;}if(r1>r)break;if(r1<=r2)ans+=b[minl[i]-i+2*N];}for(int i=mid+1;i<=r;i++)b[maxr[i]-i+2*N]=0;int l1=mid,l2=mid+1;for(int i=mid+1;i<=r;i++){while(minl[l2-1]>minr[i]&&l2>l){l2--;b[maxl[l2]+l2+2*N]++;}while(maxl[l1]<maxr[i]&&l1>=l){b[maxl[l1]+l1+2*N]--;l1--;}if(l1<l)break;if(l1>=l2)ans+=b[minr[i]+i+2*N];}for(int i=l;i<=mid;i++)b[maxl[i]+i+2*N]=0;return ans+work(l,mid)+work(mid+1,r); } int main(){scanf("%d",&n);int x,y;for(int i=1;i<=n;i++){scanf("%d%d",&x,&y);a[x]=y;}printf("%d\n",work(1,n));return 0; }

轉載于:https://www.cnblogs.com/Ren-Ivan/p/7746671.html

總結

以上是生活随笔為你收集整理的9.5题解的全部內容,希望文章能夠幫你解決所遇到的問題。

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