2020 China Collegiate Programming Contest Qinhuangdao Site 补题部分
已經補AEFGK
E. Exam Results
枚舉+二分+動態開點權值線段樹O(nlogN)O(nlogN)O(nlogN)
智商太低,想不到什么貪心只能暴力數據結構維護
對于所有學生的最高成績只可能是ai(1≤i≤n)a_i(1\leq i\leq n)ai?(1≤i≤n)或者最大的bib_ibi?,對于后面一種情況直接特殊考慮一下即可,下面主要分析最高成績是ai(1≤i≤n)a_i(1\leq i\leq n)ai?(1≤i≤n)的情況。
首先將所有學生按照aaa從大到小排序,然后依次枚舉每一個學生的aia_iai?作為最高成績,假設當前這位是aia_iai?,那么對于i→ni\to ni→n這些學生的分數肯定越大越好即所有學生的成績應該是aaa,統計i→ni\to ni→n滿足題目意思的個數只需要二分一下即可。
而對于1→i?11\to i-11→i?1這些學生,我們知道要保證當前aia_iai?是最高成績這些學生的分數一定不能是aaa,只能是bbb,因此每考慮一個學生后把當前學生的bbb加入到動態開點權值線段樹中,然后對于1→i?11\to i-11→i?1這些學生只需要直接查詢即可。
注意當前aia_iai?不能作為最高分數的情況當且僅當權值線段樹中的b的最大值大于aia_iai?
F. Friendly Group
并查集維護一下連通性即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) //#pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<queue> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int mod=1e9+7; const int N=1000010; int h[N],e[2*N],ne[2*N],idx; int p[N]; int find(int x) {return x==p[x]?x:p[x]=find(p[x]);} void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++; } pii edge[N]; bool st[N]; void dfs(int u,int fa) {st[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa||st[j]) continue;dfs(j,u);} } int main() {IO;int T=1;cin>>T;for(int ca=1;ca<=T;ca++){int n,m;cin>>n>>m;for(int i=1;i<=n;i++){p[i]=i;st[i]=0;h[i]=-1;}idx=0;for(int i=1;i<=m;i++) {int a,b;cin>>a>>b;edge[i]={a,b};add(a,b),add(b,a);}for(int i=1;i<=m;i++){int a=edge[i].first,b=edge[i].second;if(st[a]||st[b]) continue;int pa=find(a),pb=find(b);if(pa==pb)dfs(a,-1);elsep[pa]=pb;}int cnt=0;for(int i=1;i<=n;i++) cnt-=st[i];for(int i=1;i<=m;i++){int a=edge[i].first,b=edge[i].second;if(st[a]&&st[b]) cnt++;}printf("Case #%d: %d\n",ca,cnt);}return 0; }G. Good Number
按塊考慮,數學題。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) //#pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<queue> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int mod=1e9+7; const int N=200010; int n; int main() {IO;int T=1;cin>>T;for(int ca=1;ca<=T;ca++){ll res=0;ll n,k;cin>>n>>k;if(k==1||k>=30){printf("Case #%d: %d\n",ca,n);continue;}ll m=pow(n,1.0/k);for(int i=1;i<=m;i++){ll l=pow(i,k);ll r=min(n,(long long)pow(i+1,k)-1);res+=r/i-(l-1)/i;}printf("Case #%d: %d\n",ca,res);}return 0; }K. Kingdom’s Power
大佬題解1大佬題解2
看了大佬的題解,我想了一個貪心:把所有葉子拿出來,然后按照深度排序,依次遍歷每個葉子,當前葉子對答案的貢獻:要么從前一個葉子過來的費用(lca求一下即可)要么從根節點過來的費用。然而TLE了,也不知道這樣貪心對不對先記下來吧。順便存個tarjan求lca的板子
錯誤orTLE代碼
//TLE #define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<queue> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int mod=1e9+7; const int N=1000010; int h[N],e[N],ne[N],idx; void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;} int dep[N]; int res,n; int leaf[N],cnt; bool cmp(int x,int y){return dep[x]<dep[y];} void dfs1(int u) {int now=0;for(int i=h[u];i!=-1;i=ne[i]){int t=e[i];now++;dep[t]=dep[u]+1;dfs1(t);}if(!now) leaf[++cnt]=u; } // tarjan 求lca vector<pii> q[N]; int anc[N],st[N],p[N]; int find(int x) {return x==p[x]?x:p[x]=find(p[x]);} void tarjan(int u) {st[u]=1;//遍歷但未回溯for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(!st[j]){tarjan(j);//遍歷子樹p[j]=u;//合并節點}}for(auto &t:q[u]){int y=t.first,id=t.second;if(st[y]==2)anc[id]=find(y);}st[u]=2;//結束回溯 } int main() {//IO;int T=1;scanf("%d",&T);for(int ca=1;ca<=T;ca++){cin>>n;for(int i=1;i<=n;i++) {h[i]=-1;dep[i]=0;p[i]=i;st[i]=0;q[i].clear();}idx=cnt=res=0;for(int i=2;i<=n;i++) {int p;scanf("%d\n",&p);add(p,i);}dfs1(1);sort(leaf+1,leaf+1+cnt,cmp);for(int i=2;i<=cnt;i++){q[leaf[i]].push_back({leaf[i-1],i});q[leaf[i-1]].push_back({leaf[i],i});}tarjan(1);int res=dep[leaf[1]];for(int i=2;i<=cnt;i++)res+=min(dep[leaf[i]],dep[leaf[i]]+dep[leaf[i-1]]-2*dep[anc[i]]);printf("Case #%d: %d\n",ca,res);}return 0; }AC代碼
按照上述博客寫的代碼
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) //#pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<queue> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int mod=1e9+7; const int N=1000010; vector<int> e[N]; int dep[N],dist[N]; int res,n; bool cmp(int x,int y) {return dist[x]<dist[y];}; void dfs1(int u) {for(auto &t:e[u]){dep[t]=dep[u]+1;dfs1(t);dist[u]=max(dist[u],dist[t]+1);}sort(e[u].begin(),e[u].end(),cmp); } int dfs2(int u,int cnt) {if(e[u].empty()) return res+=cnt,1;for(auto &t:e[u]) cnt=min(dep[u],dfs2(t,cnt+1));return cnt+1; } int main() {IO;int T=1;cin>>T;for(int ca=1;ca<=T;ca++){cin>>n;for(int i=1;i<=n;i++) {e[i].clear();dep[i]=dist[i]=0;}res=0;for(int i=2;i<=n;i++) {int p;cin>>p;e[p].push_back(i);}dfs1(1);dfs2(1,0);printf("Case #%d: %d\n",ca,res);}return 0; }總結
以上是生活随笔為你收集整理的2020 China Collegiate Programming Contest Qinhuangdao Site 补题部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 唱歌的电脑配置怎么看(唱歌的电脑配置)
- 下一篇: mex性质学习