Codeforces 802 补题
codeforces802 A-O?Helvetic Coding Contest 2017 online mirror?
?
A ?Heidi and Library (easy)
水題 同B
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; const int maxn=1000000; int n,k,a[maxn],num; bool ex[maxn],need[maxn]; int main() {//freopen("t.txt","r",stdin);scanf("%d%d",&n,&k);num=0;memset(ex,0,sizeof(ex));for(int i=0;i<n;i++)scanf("%d",&a[i]);int ans=0;for(int i=0;i<n;i++){if(ex[a[i]]) continue; if(num<k){num++;ans++;ex[a[i]]=true;}else{int sum=0;memset(need,0,sizeof(need));for(int j=i+1;j<n&&sum<k-1;j++){if(!ex[a[j]])continue;if(need[a[j]]==false)sum++;need[a[j]]=true;}for(int j=1;j<=n;j++){if(ex[j]&&(!need[j])){ex[j]=false;ex[a[i]]=true;ans++;break;}}}}printf("%d\n",ans);return 0; }
B ?Heidi and Library (medium)
經(jīng)典的內(nèi)存管理OPT算法
不過基本沒有實(shí)際應(yīng)用價(jià)值,因?yàn)椴僮飨到y(tǒng)不可能知道之后要調(diào)用哪些內(nèi)存。
用map或者堆都可以實(shí)現(xiàn) 堆會(huì)快很多
map版本
#include <bits/stdc++.h> using namespace std; set<int> s; int n,cs,k,c[400400],ne[400400],la[400400],cc;int main(){scanf("%d %d",&n,&k);for(int i=0;i<n;i++)scanf("%d",&c[i]);for(int i=n-1;i>=0;i--){if(!la[c[i]])ne[i]=1e6,la[c[i]]=i;else ne[i]=la[c[i]],la[c[i]]=i;}for(int i=0;i<n;i++){if(s.count(i)){s.erase(i),s.insert(ne[i]);continue;}if((int)s.size()<k)s.insert(ne[i]),cc++;else s.erase(--s.end()),s.insert(ne[i]),cc++;}printf("%d\n",cc); }優(yōu)先隊(duì)列版本
??
#include<cstdio> #include<cstdlib> #include<cstring> #include<stack> #include<deque> #include<queue> using namespace std; const int maxn=500000; int n,k,a[maxn],num,ne[maxn],ls[maxn]; bool ex[maxn]; priority_queue<int>que; int main() {//freopen("t.txt","r",stdin);while(!que.empty())que.pop();scanf("%d%d",&n,&k);num=0;memset(ex,0,sizeof(ex));for(int i=0;i<n;i++)scanf("%d",&a[i]);for(int i=n-1;i>=0;i--){if(!ls[a[i]])ls[a[i]]=1e+8;ne[i]=ls[a[i]];ls[a[i]]=i;}int ans=0;int j=1;int maxv=0,max2v=0;for(int i=0;i<n;i++){if(ex[i]){while(que.size()>0&&que.top()<=i)que.pop();ex[i]=false;if(ne[i]<=n)ex[ne[i]]=true;que.push(ne[i]);continue; }if(num<k){num++;ans++;if(ne[i]<=n)ex[ne[i]]=true;que.push(ne[i]);}else{int nowv=que.top();que.pop();ans++;if(nowv<=n)ex[nowv]=false;if(ne[i]<=n)ex[ne[i]]=true;que.push(ne[i]);}}printf("%d\n",ans);return 0; }
C?Heidi and Library (hard)
費(fèi)用流
考慮最暴力的方法,每次調(diào)用新的書都直接購買,這多半不是最優(yōu)解。
有沒有辦法優(yōu)化到最優(yōu)解呢?
考慮對(duì)于書架上的每一個(gè)位置,讓它在恰當(dāng)?shù)臅r(shí)候繼續(xù)持有書,在恰當(dāng)?shù)臅r(shí)候購買新的書,這樣我們就能找到最優(yōu)解了。
對(duì)于相同的書,連一條費(fèi)用為-c[]的邊(持有即相當(dāng)于不用買新的所以答案-c[]),不同的書連一條費(fèi)用為0的邊.
#include<bits/stdc++.h> using namespace std;typedef long long LL;#define N 200020const LL INF = 1e9;int nxt[N], cost[N], cap[N], to[N], head[N], cnt;void init(){memset(head, -1, sizeof head); }void add_Edge(int S, int T, int c, int w){nxt[cnt] = head[S], to[cnt] = T, cap[cnt] = c, cost[cnt] = w, head[S] = cnt ++;nxt[cnt] = head[T], to[cnt] = S, cap[cnt] = 0, cost[cnt] = -w, head[T] = cnt ++; }int prv[N], vis[N]; LL dist[N];LL SPFA(int S, int T, int vet){queue <int> Q;fill(dist, dist + vet, INF);fill(prv, prv + vet, -1);dist[S] = 0, Q.push(S), vis[S] = true;while(!Q.empty() ){int x = Q.front();Q.pop(), vis[x] = false;for(int id = head[x]; ~id; id = nxt[id]) if( cap[id] ){int y = to[id];if(dist[y] > dist[x] + cost[id]){dist[y] = dist[x] + cost[id];prv[y] = id;if(!vis[y]) Q.push(y), vis[y] = true;}}}if(!~prv[T]){ return INF; }int cur = T;while( cur != S ) {cur = prv[cur];cap[cur] --;cap[cur xor 1] ++;cur = to[cur xor 1];}return dist[T]; }int a[N], c[N], n, m;int main(){//freopen("t.txt", "r", stdin);scanf("%d %d", &n, &m);for(int i = 1; i <= n; i ++) scanf("%d", a + i);for(int i = 1; i <= n; i ++) scanf("%d", c + i);init();LL ans = 0;int S = n + 1, T = 2 * n + 2;for(int i = 1; i <= n; i ++){ans += c[a[i]];add_Edge(S, i, 1, 0);add_Edge(i, S + i, 1, -INF);for(int j = i + 1; j <= n; j ++){if(a[i] == a[j]) add_Edge(i + S, j, 1, -c[a[j]]);else add_Edge(i + S, j, 1, 0);}add_Edge(i + S, T, 1, 0);}for(int step = 1; step <= m; step ++){LL tmp = SPFA(S, T, T + 1);if(tmp >= 0) break;ans += tmp;}cout << ans + INF * n << endl; }
D?Marmots (easy)
根據(jù)泊松分布的特點(diǎn),對(duì)稱軸兩邊的概率密度最大。
用這個(gè)特點(diǎn)來判斷是泊松分布還是平均分布。
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int a[250],b[250]; int main() {int T;scanf("%d",&T);while(T--){for(int i=0;i<250;i++)scanf("%d",&a[i]);//for(int i=0;i<250;i++)scanf("%d",&b[i]);int mina=a[0],maxa=a[0],minb=b[0],maxb=b[0];double mida=0;for(int i=0;i<250;i++){mida+=a[i];//minb=min(minb,b[i]);maxb=max(maxb,b[i]);}mida/=250.;int sum=0,sumb=0;double len=mida/2;for(int i=0;i<250;i++){if(a[i]>(mida-len)&&a[i]<(mida+len))sum++;if(a[i]<=1)sumb++;}if(sum<180||sumb>3)printf("uniform\n");else printf("poisson\n");}return 0; }
E?Marmots (medium)
在D的基礎(chǔ)上,首先判斷是 泊松分布還是平均分布
如果是泊松分布求所有值的平均值,否則求最大值和最小值的平均值。
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int a[250],b[250]; int main() {int T;scanf("%d",&T);while(T--){for(int i=0;i<250;i++)scanf("%d",&a[i]);//for(int i=0;i<250;i++)scanf("%d",&b[i]);double mina=a[0],maxa=a[0],minb=b[0],maxb=b[0];double mida=0;for(int i=0;i<250;i++){mida+=a[i];mina=min(mina,(double)a[i]);maxa=max(maxa,(double)a[i]);}mida/=250.;int sum=0,sumb=0;double len=mida/2;for(int i=0;i<250;i++){if(a[i]>(mida-len)&&a[i]<(mida+len))sum++;if(a[i]<=1)sumb++;}if(sum<180||sumb>3)//printf("uniform\n");{printf("%.0lf\n",(mina+maxa)/2+0.5);}else //printf("poisson\n");{printf("%.0lf\n",mida+0.5);}}return 0; }
F?Marmots (hard)
由于出現(xiàn)了負(fù)數(shù),所以D中簡(jiǎn)單粗暴的方法不可取了。
不過數(shù)據(jù)并沒有變復(fù)雜,由于平均分布相對(duì)于泊松分布更加離散,所以方差會(huì)有明顯的區(qū)別。
利用方差來判斷,就不怕負(fù)數(shù)了。
#include<bits/stdc++.h> #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,a,b) for (int i=a;i>=b;i--) using namespace std;inline int read() {int x=0,f=1; char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+(ch^48); ch=getchar();}return x*f; }const int N = 251; const int P = 1005; const double e = 2.718281828459045235360287471352;int a[N]; double tp1[P<<1],tp2[P<<1];int main() {int T=read();while (T--) {int mx=0;double mean=0; rep(i,1,250) a[i]=read(),mean+=a[i],mx=max(mx,a[i]);double D=0; mean/=250; rep(i,1,250) D+=a[i]*a[i];D/=(double)250; D-=mean*mean;double sigma = sqrt(D);if (mx/sigma<=1.9) puts("uniform"); else puts("poisson");} return 0; }
G?Fake News (easy)
公共子序列問題 O(N^2)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<string> #include<vector> #include<cstring> using namespace std; int dp[1000][1000]; int LCS(int n1,int n2,string s1,string s2) {for(int i=0;i<n1;i++)for(int j=0;j<n2;j++){if(i>0)dp[i][j]=dp[i-1][j];if(j>0&&dp[i][j-1]>dp[i][j])dp[i][j]=dp[i][j-1];if(s1[i]==s2[j]){if(i==0||j==0)dp[i][j]=1;else dp[i][j]=dp[i-1][j-1]+1; }}return dp[n1-1][n2-1]; } int main() {//freopen("t.txt","r",stdin);ios::sync_with_stdio(false);string s1,s2;s2="heidi";while(cin>>s1){memset(dp,0,sizeof(dp));int len=LCS(s1.length(),s2.length(),s1,s2);if(len==5)printf("YES\n");else printf("NO\n");s1.clear();s2.clear(); }return 0; }
H?Fake News (medium)
很簡(jiǎn)單的一道計(jì)數(shù)題 直接看代碼吧~
#include<cstdio> #include<algorithm> using namespace std; int Comb[110][6], C[110], S; int main(){int i, j;for(i=0;i<=45;i++){Comb[i][0]=1;for(j=1;j<=5&&j<=i;j++)Comb[i][j]=Comb[i-1][j]+Comb[i-1][j-1];}scanf("%d",&S);for(i=45;i>=5;i--){while(S>=Comb[i][5]){C[i]++;S-=Comb[i][5];}}for(i=0;i<45;i++){while(C[i]--)printf("b");printf("a");}printf(" aaaaab\n"); }
I?Fake News (hard)
后綴數(shù)組+記憶化搜索
很有趣的一道后綴數(shù)組題
題目的意思就是讓我們求一個(gè)字符串L所有子串在這個(gè)串中出現(xiàn)的次數(shù)。
這種問題用腳指頭想都知道肯定要上后綴數(shù)組啦!
對(duì)于數(shù)組height[l...r] 其中的最小值就是他們的公共前綴的長(zhǎng)度,而這個(gè)公共前綴就是L的一個(gè)唯一的子串。r-l+1就是它出現(xiàn)的次數(shù)。(ps:不懂height數(shù)組的自行學(xué)習(xí)后綴數(shù)組再來看)
怎樣高效統(tǒng)計(jì)呢?
對(duì)于height[0,len(L)-1]我們能否高效的找到它的最小值?可以。
那么假設(shè)最小值的位置是mid 然后我們把height分成l..mid mid+1....r分別計(jì)算,那么怎么合并呢?
兩個(gè)子片段的公共最小Height值就是他們的公共前綴長(zhǎng)度,我們可以知道這個(gè)公共前綴出現(xiàn)的次數(shù),但是同時(shí)要排除他們?cè)谧执胸暙I(xiàn)的值。
太難描述了,具體轉(zhuǎn)移方法看代碼吧。
注意,mid一定是最小值所在的位置,不可以隨意劃分height數(shù)組,那樣是錯(cuò)的。
求mid不能太暴力,會(huì)TLE。
#include <iostream> #include <cstring> #include <cstdio> #include<vector> using namespace std; const int MAX = 100500; const int nMAX = 105; const int mMAX = 1005; int strnum; char str[MAX]; int source[MAX]; int sa[MAX], rk[MAX], height[MAX]; int wa[MAX], wb[MAX], wv[MAX], wd[MAX]; bool vis[nMAX]; int id[MAX]; int anslen, anspos[mMAX], ansnum; const int MAXN=200000+100; void radix(int *str,int *a,int *b,int n,int m) {static int count[MAXN];memset(count,0,sizeof(count));for(int i=0;i<n;++i)++count[str[a[i]]];for(int i=1;i<=m;++i)count[i]+=count[i-1];for(int i=n-1;i>=0;--i)b[--count[str[a[i]]]]=a[i]; }void sorted_suffix_array(int *str,int *sa,int n,int m) {static int rank[MAXN],a[MAXN],b[MAXN];for(int i=0;i<n;++i)rank[i]=i;radix(str,rank,sa,n,m);rank[sa[0]]=0;for(int i=1;i<n;++i)rank[sa[i]]=rank[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);for(int i=0;(1<<i) <n;++i){for(int j=0;j<n;++j){a[j]=rank[j]+1;b[j]=j+(1<<i)>=n? 0:rank[j+(1<<i)]+1;sa[j]=j;}radix(b,sa,rank,n,n);radix(a,rank,sa,n,n);rank[sa[0]]=0;for(int j=1;j<n;++j){rank[sa[j]]=rank[sa[j-1]]+(a[sa[j-1]]!=a[sa[j]]||b[sa[j-1]]!=b[sa[j]]);}} }void calc_height(int *str,int *sa,int *h,int n) {static int Rank[MAXN];int k=0;h[0]=0;for(int i=0;i<n;++i)Rank[sa[i]]=i;for(int i=0;i<n;++i){k= k==0?0:k-1;if(Rank[i]!=0)while(str[i+k]==str[sa[Rank[i]-1]+k])++k;h[Rank[i]]=k;} } int stlen; long long dp(long long l,long long r,long long &summ,vector<int>&nemi,int flag) {if(l==r){summ=(long long)stlen-(long long)sa[l];return summ;}int mid=-1;vector<int>nemr;if(flag!=-1)mid=nemi[flag]-1;else{nemi.push_back(l+1);for(int i=l+1;i<r;i++){if(height[i+1]<height[nemi[(int)nemi.size()-1]])nemi.push_back(i+1);}flag=(int)nemi.size()-1;mid= nemi[flag]-1;}long long sum1,sum2;long long int minh=min(min(dp(l,mid,sum1,nemi,flag-1),dp(mid+1,r,sum2,nemr,-1)),(long long)height[mid+1]);summ=sum1+sum2+minh*(r-l+1)*(r-l+1)-minh*(mid-l+1)*(mid-l+1)-minh*(r-mid)*(r-mid);nemr.clear();return minh; }long long int solve(char *st){stlen=strlen(st);for(int i=0;i<stlen;i++)source[i]=st[i]-'a'+1;sorted_suffix_array(source,sa,(int)stlen,126);calc_height(source,sa,height,(int)stlen);height[0]=1e+8;long long int ans=0;vector<int>mi;mi.clear();dp(0,stlen-1,ans,mi,-1);return ans; } int main() {//freopen("t.txt","r",stdin);int T;scanf("%d",&T);while(T--){scanf("%s",&str);printf("%I64d\n",solve(str));}return 0; }
J?Send the Fool Further! (easy)
水題
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<string> #include<vector> #include<cstring> using namespace std; vector<int>adj[200]; int w[200][200]; int dist[200]; void dfs(int cur,int fa,int len) {for(int i=0;i<adj[cur].size();i++){int ne=adj[cur][i];if(ne==fa)continue;dist[ne]=min(dist[ne],len+w[cur][ne]);dfs(ne,cur,len+w[cur][ne]);} } int main() {//freopen("t.txt","r",stdin);int n;scanf("%d",&n);int u,v;for(int i=0;i<n-1;i++){scanf("%d%d",&u,&v);scanf("%d",&w[u][v]);w[v][u]=w[u][v];adj[u].push_back(v);adj[v].push_back(u);}for(int i=1;i<n;i++)dist[i]=99999999;dist[0]=0;dfs(0,-1,0);int ans=0;for(int i=0;i<n;i++)ans=max(ans,dist[i]);printf("%d\n",ans);return 0; }
K?Send the Fool Further! (medium)
比較有趣的樹形DP
考慮最優(yōu)解,必有兩種情況,要么在0結(jié)束,要么不在0結(jié)束。對(duì)于其他節(jié)點(diǎn)也是一個(gè)道理。
所以設(shè)dp[i][bool]為從i出發(fā),的最優(yōu)解,bool為0則最后回到i否則不用回到i
轉(zhuǎn)移方程直接看程序吧 很簡(jiǎn)單。
#include <bits/stdc++.h> using namespace std;const int maxn = 200000; int dp[maxn][2]; vector< pair<int,int> > E[maxn]; int n,k;bool cmp(const pair<int,int> &a, const pair<int,int> &b){return (a.first > b.first); }void dfs(int u, int p){vector< pair<int,int> > c;set<int> st;for(auto e: E[u]){int v = e.first;int cst = e.second;if(v == p) continue;dfs(v,u);c.push_back({dp[v][0] + cst,v});}sort(c.begin(), c.end(), cmp);int tk = min(k-1, (int)(c.size()));for(int i = 0; i < tk; i++){dp[u][0] += c[i].first;st.insert(c[i].second);}int extra = 0;if(tk != (int)(c.size()))extra = c[tk].first;for(auto e: E[u]){int v = e.first;int cst = e.second;if(v == p) continue;if(st.count(v) == 0)dp[u][1] = max(dp[u][1], dp[v][1] + dp[u][0] + cst);elsedp[u][1] = max(dp[u][1], dp[u][0] - dp[v][0] + extra + dp[v][1]);}st.clear();c.clear(); }int main(){scanf("%d%d", &n, &k);for(int i = 1; i < n; i++){int u,v,c;scanf("%d%d%d", &u, &v, &c);E[u].push_back({v,c});E[v].push_back({u,c});}dfs(0,-1);cout << max(dp[0][0], dp[0][1]) << "\n";return 0; }
?
L?Send the Fool Further! (hard)
這道題題意說的不是很清楚 總的來說是讓我們求E(0)
E(0)和E(v)有線性關(guān)系,v是0的孩子。
所以,暴力解方程組的方法是可以求出來的。但是復(fù)雜度太高O(n^3)
有沒有聰明一點(diǎn)的方法呢?
還是考慮E(0)和E(v)的關(guān)系
E(v)由它的孩子和E(0)線性組合而成。假設(shè)E(v)不考慮0的情況下期望為G(v)G(v)可以在dfs()的過程中求出來。
我們通過一定的代數(shù)變形可以直接由G(v)推出E(v)
嗯。。大致就是這樣。。還是那句話 近世代數(shù)太重要了。
代碼很清晰
直觀的看的話 在樹上求解問題,最關(guān)鍵的就是找出遞歸關(guān)系,
也就是對(duì)于當(dāng)前節(jié)點(diǎn)求解(做到)不需考慮它的父親部分(這樣我們離答案就很近了因?yàn)樽詈蟮拇鸢窯【0】就是不需要考慮父親的)。
?
#include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <string> #define SIZE 100005 #define MOD 1000000007using namespace std; typedef long long int ll;struct edge {int to,cost;edge(int to=0,int cost=0):to(to),cost(cost){} }; vector <edge> vec[SIZE]; ll F[SIZE],G[SIZE]; int nd[SIZE]; int n;ll mpow(ll m,ll t) {if(t==0) return 1LL;ll ret=mpow(m*m%MOD,t/2);if(t%2==1) ret=ret*m%MOD;return ret; } ll inv(ll m) {return mpow(m,MOD-2); } void dfs(int v=0,int p=-1) {if(vec[v].size()==1){F[v]=G[v]=0;return;}ll sumG=0,sumF=vec[v].size();for(int i=0;i<vec[v].size();i++){edge e=vec[v][i];sumG+=e.cost;if(sumG>=MOD) sumG-=MOD;if(e.to!=p){dfs(e.to,v);sumG+=G[e.to];if(sumG>=MOD) sumG-=MOD;sumF-=F[e.to];if(sumF<0) sumF+=MOD;}}ll g=inv(sumF);F[v]=g;G[v]=g*sumG%MOD; } int main() { freopen("t.txt","r",stdin);scanf("%d",&n);for(int i=0;i<n-1;i++){int a,b,c;scanf("%d %d %d",&a,&b,&c);vec[a].push_back(edge(b,c));vec[b].push_back(edge(a,c));}dfs();printf("%lld\n",G[0]);return 0; }
M?April Fools' Problem (easy)
每個(gè)序列排序后前k個(gè)數(shù)的和
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int num[3000]; int main() {//freopen("t.txt","r",stdin);int n,m,t;int mins=-1;scanf("%d%d",&n,&m);for(int i=0;i<n;i++){scanf("%d",&num[i]);}sort(num,num+n);int ans=0;for(int i=0;i<m;i++)ans+=num[i];printf("%d\n",ans);return 0; }N?April Fools' Problem (medium)
?很有趣的一道貪心題。
給定兩個(gè)正整數(shù)序列A和B
求兩個(gè)A和B的長(zhǎng)度為k的子序列 a和b滿足 a中的第i個(gè)元素在A中的位置<=?b中的第i個(gè)元素在B中的位置 并且和最小。
用貪心的方法,先求一個(gè)最小的合法解 a[i]和b[j]且 j>=i,然后他們之間[i...j]就可以放反向的數(shù)對(duì)了也就是在找最小解的時(shí)候可以允許j<i了 。
#include<bits/stdc++.h> using namespace std; typedef long long int LL ; const int maxn=3000; LL a[maxn],b[maxn],va[maxn],vb[maxn],verse[maxn]; int n,k; int main() {//freopen("t.txt","r",stdin);scanf("%d%d",&n,&k);for(int i=0;i<n;i++)scanf("%I64d",&a[i]);for(int i=0;i<n;i++)scanf("%I64d",&b[i]);LL ans=0;b[n]=1e+18;while(k--){int ra=-1,rb;for(int i=n-1,j=n,minb=n;i>=0;i--){if(j>i)j=i;if(b[j]<b[minb]&&!vb[j])minb=j;while((j-1)>=0&&verse[j-1])if(b[--j]<b[minb]&&!vb[j])minb=j;if(!va[i]&&(ra==-1||a[i]+b[minb]<a[ra]+b[rb]))ra=i,rb=minb;}ans+=a[ra]+b[rb];va[ra]++;vb[rb]++;for(int i=ra;i<rb;i++)verse[i]++;for(int i=rb;i<ra;i++)verse[i]--;}printf("%I64d\n",ans);return 0; }
O?April Fools' Problem (hard)
題意和N一樣 數(shù)據(jù)提高到了500000 非常有趣的一道優(yōu)化題
顯然N中我們O(n^2)的算法要TLE
有什么辦法優(yōu)化到O(nlogn)么?
1.首先考慮當(dāng)前已經(jīng)選定了N個(gè)題目以及他們合法的打印時(shí)間,對(duì)于以后可選的打印時(shí)間,可以用來優(yōu)化答案。O(n)
2.那么主要問題就變成了如何選取恰當(dāng)?shù)腘個(gè)初始題目。
我們用二分的方法選取一個(gè)閥值mid 比它更優(yōu)的 我們才讓它成為備選題目,這樣不斷二分mid 總會(huì)找到一個(gè)最恰當(dāng)?shù)膍id使得選中的題目正好是m個(gè)最優(yōu)的。
當(dāng)然如果出現(xiàn)比m多的情況說明他們是相等的題目和打印時(shí)間。
看代碼吧 很清晰。
#include <bits/stdc++.h> using namespace std;typedef long long LL;#define N 500050priority_queue <LL, vector <LL>, greater<LL> > Qa; priority_queue <LL> Qb;LL a[N], b[N]; int n, m;const LL INF = 1e13;int main() { // freopen("in.txt", "r", stdin);scanf("%d %d", &n, &m);for (int i = 1; i <= n; i ++) scanf("%I64d", a + i);for (int i = 1; i <= n; i ++) scanf("%I64d", b + i);LL st = 0, en = INF, ans = 0;while (st <= en ) {LL mid = (st + en) >> 1;while ( !Qa.empty() ) Qa.pop();while ( !Qb.empty() ) Qb.pop();LL tmp = 0;int sz = 0;for (int i = 1; i <= n; i ++) {Qa.push(a[i]);LL tmp1 = Qa.top() + b[i] - mid;LL tmp2 = Qb.empty() ? INF : b[i] - Qb.top();if (tmp1 <= tmp2 && tmp1 <= 0) {tmp += tmp1; sz ++;Qb.push(b[i]);Qa.pop();}else if (tmp2 < tmp1 && tmp2 < 0){tmp += tmp2;Qb.pop();Qb.push(b[i]);}}if (sz >= m) {ans = tmp + m * mid;en = mid - 1;}else {st = mid + 1;}}cout << ans << endl; }
轉(zhuǎn)載于:https://www.cnblogs.com/heisenberg-/p/6916520.html
總結(jié)
以上是生活随笔為你收集整理的Codeforces 802 补题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python经典例题:跑马灯文字效应
- 下一篇: 核壳油溶性CaSe/CdS/ZnS量子点