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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

牛客练习赛 61(待补F-点分治?)

發布時間:2023/12/3 编程问答 111 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客练习赛 61(待补F-点分治?) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

A. 打怪

先求出每次打死一只怪需要掉多少血,然后就直接算出能夠打死多少只。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; int main() {IO;int T=1;cin>>T; while(T--){int h,a,H,A;cin>>h>>a>>H>>A;int cnt=(H+a-1)/a;int p=(cnt-1)*A;if(p) cout<<(h-1)/p<<'\n';else cout<<"-1\n";}return 0; }

B. 吃水果

不妨設n<mn<mn<m,如果我們先吃kkk次然后加倍一次能夠使得m=nm=nm=n那么需要滿足2×(n?k)=m?k2×(n-k)=m-k2×(n?k)=m?k,得出k=2n?mk=2n-mk=2n?m,由此只需先讓加倍到2n>=m2n>=m2n>=m然后吃kkk次再次加倍然后在吃m?km-km?k次即可吃完,由此上面貪心一定最小。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; int main() {IO;int T=1;cin>>T;while(T--){int n,m;cin>>n>>m;if(n>m) swap(n,m);int res=m;while(n<m){res++;n*=2;}cout<<res<<'\n';} return 0; }

C. 四個選項

首先先用并查集統計出每個連通塊的數量,然后把每一個連通塊看成一個物品,跑一邊背包問題即可。
狀態表示:f(i,j,k,l,r)f_{(i,j,k,l,r)}f(i,j,k,l,r)?考慮前iii個物品,答案A選了jjj個,答案B選了kkk個,答案C選了lll個,答案D選了rrr個的集合。
狀態轉移:考慮第iii個物品放在哪個答案中不難寫出轉移。
感覺這方法有點暴力,但是思路應該還是非常好理解

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=15; int p[N],sz[N]; ll f[N][N][N][N][N]; int find(int x) {return x==p[x]?x:p[x]=find(p[x]); } int main() {IO;int T=1;//cin>>T;while(T--){for(int i=1;i<=12;i++) p[i]=i,sz[i]=1;int a,b,c,d,m;cin>>a>>b>>c>>d>>m;vector<int> v;v.push_back(0);while(m--){int a,b;cin>>a>>b;int pa=find(a),pb=find(b);if(pa==pb) continue;sz[pb]+=sz[pa];p[pa]=pb;}for(int i=1;i<=12;i++) if(p[i]==i) v.push_back(sz[i]);f[0][0][0][0][0]=1;int n=v.size()-1;for(int i=1;i<=n;i++)for(int j=0;j<=a;j++)for(int k=0;k<=b;k++) for(int l=0;l<=c;l++)for(int r=0;r<=d;r++){if(j>=v[i]) f[i][j][k][l][r]+=f[i-1][j-v[i]][k][l][r];if(k>=v[i]) f[i][j][k][l][r]+=f[i-1][j][k-v[i]][l][r];if(l>=v[i]) f[i][j][k][l][r]+=f[i-1][j][k][l-v[i]][r];if(r>=v[i]) f[i][j][k][l][r]+=f[i-1][j][k][l][r-v[i]];}cout<<f[n][a][b][c][d]<<'\n';}return 0; }

D.最短路變短了

原圖跑一邊dijsktra算出dist1[i]表示1~i的最短距離,在跑一邊反圖算出dist2[i]表示i~n的最短距離。
考慮如果u→vu\to vuv之間的邊取反能夠縮短1→n1\to n1n的最短距離,那么說明目前最短路徑一定是1→?→v→u→?→n1\to \dots \to v\to u\to \dots \to n1?vu?n,因此只需要判斷該條件是否成立即可得到答案(dist1[v]+dist2[u]+c<dist1[n])

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<ll,int> pli; const int N=100010,M=400010; int h1[N],h2[N],e[M],ne[M],idx; ll w[M]; ll dist1[N],dist2[N]; bool st[N]; struct node {int u,v;ll w; }E[M]; int n,m,q; void add(int h[],int a,int b,ll c) {e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++; } void dijkstra(int start,int h[],ll dist[]) {memset(dist,0x3f,8*N);memset(st,0,sizeof st);priority_queue<pli,vector<pli>,greater<pli> >q;dist[start]=0;q.push({0,start});while(q.size()){int t=q.top().second;q.pop();if(st[t]) continue;st[t]=1;for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(dist[j]>dist[t]+w[i]){dist[j]=dist[t]+w[i];q.push({dist[j],j});}}} } int main() {IO;int T=1;//cin>>T;while(T--){memset(h1,-1,sizeof h1);memset(h2,-1,sizeof h2);cin>>n>>m;for(int i=1;i<=m;i++){cin>>E[i].u>>E[i].v>>E[i].w;add(h1,E[i].u,E[i].v,E[i].w);add(h2,E[i].v,E[i].u,E[i].w);}dijkstra(1,h1,dist1);dijkstra(n,h2,dist2);cin>>q;while(q--){int id;cin>>id;int u=E[id].u,v=E[id].v,c=E[id].w;if(dist1[n]>dist1[v]+dist2[u]+c) cout<<"YES\n";else cout<<"NO\n";}}return 0; }

E.相似的子串

字符串哈希+二分
二分掃一遍序列即可,用哈希表記錄出現次數已經最后一次出現的位置。
時間復雜度O(nlogn)O(nlogn)O(nlogn)

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<unordered_map> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const int N=200010,P=131; unordered_map<ull,pii> mp; ull h[N],p[N]; int n,k; char s[N]; ull get(int l,int r) {return h[r]-h[l-1]*p[r-l+1]; } bool check(int mid) {mp.clear();for(int i=mid;i<=n;i++){ull v=get(i-mid+1,i);if(mp[v].second<=i-mid) {mp[v].first++;mp[v].second=i;if(mp[v].first>=k) return 1;}}return 0; } int main() {IO;int T=1;//cin>>T;while(T--){cin>>n>>k;cin>>s+1;p[0]=1;for(int i=1;i<=n;i++){p[i]=p[i-1]*P;h[i]=h[i-1]*P+s[i]-'a'+1;}int l=0,r=n;while(l<r){int mid=l+r+1>>1;if(check(mid)) l=mid;else r=mid-1;}cout<<l<<'\n';}return 0; }

F.蘋果樹

點分治?待補?

總結

以上是生活随笔為你收集整理的牛客练习赛 61(待补F-点分治?)的全部內容,希望文章能夠幫你解決所遇到的問題。

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