文章目录

  • G Group Homework
  • J. Permutation Puzzle
  • K. Barrel Theory
  • B. Code With No Forces

题目链接: https://codeforces.com/gym/104008

G Group Homework

题目大意:在树上选出两条链,使得在两条链选中的点中,只被一条链选中的点的点权和最大。
题解:显然两条链要么不相交,要么只相交于一个点。因为如果两条链相交的点多于一个,那一定可以通过交换链的端点的方法使得答案更优。这个结论可以参考出题人给出的示意图,如下图:

因此,问题转化为求两条不相交的链的点权和以及求以一个点为根的最大的四个儿子的深度和。我们很容易能够想到可以使用换根dp的方法来解决这两个问题,问题在于码量较大,细节较多,不是很容易实现。
具体讲一下dp的过程,可以先将1号点作为根,维护每个点的深度 h x h_x hx​和最长链的长度 l x l_x lx​,来完成将1看作根结点的求解:
h x = m a x { h s o n } + a x l x = m a x { l s o n , h s o n 1 + h s o n 2 + a x } h_x=max\{ h_{son}\}+a_x \\ l_x=max\{l_{son},h_{son1}+h_{son2}+a_x\} hx​=max{hson​}+ax​lx​=max{lson​,hson1​+hson2​+ax​}
其中, h s o n 1 h_{son1} hson1​和 h s o n 2 h_{son2} hson2​分别表示 x x x的两个最大的儿子深度值。可以通过将 x x x的所有儿子的 h h h值排序的方法来得到。

然后再考虑如何换根,假设当前结点为 x x x,换根结点为 i i i,也就是说,在以 x x x为根的树中, i i i结点是 x x x结点的儿子结点。
我们可以先将 x x x结点的所有儿子的 l l l和 h h h全部取出,然后从大到小排序,这样就可以通过将前四大的 h h h值加和来更新答案,也就是四个最大的儿子的深度,下面考虑两条不相交的链的情况。
首先考虑 x x x结点:换根之后深度 h x h_x hx​显然不能再从 i i i结点转移而来,而应该从其他儿子的最大值中转移得到,所以我们只需要判断 h i h_i hi​结点是否是最大的值即可,是最大值就从次大的 h h h值中转移,不是最大值就不需要更新。最长链 l x l_x lx​显然也不能从结点 i i i来更新,因此先判断 l i l_i li​和 l l l的最大值之间的关系,决定是否从次大的 l l l值中转移。然后还要判断 h i h_i hi​和前二大 h h h值的关系,因为需要用到除了 h i h_i hi​之外的前两大结点进行转移。
h x = m a x { h s o n } + a x ( s o n ≠ i ) l x = m a x { l s o n , h s o n 1 + h s o n 2 + a x } ( s o n , s o n 1 , s o n 2 ≠ i ) h_x=max\{ h_{son}\}+a_x ~~~(son\neq i)\\ l_x=max\{l_{son},h_{son1}+h_{son2}+a_x\}~~~(son,son1,son2\neq i) hx​=max{hson​}+ax​   (son=i)lx​=max{lson​,hson1​+hson2​+ax​}   (son,son1,son2=i)
这时,我们求得了以 x x x为根且不含 i i i这个儿子的最长链长度和以 i i i为根且不包含 x x x这个儿子的最长链长度,因此这两条最长链一定不交,可以用来更新答案。
然后再考虑结点 i i i,相当于多了一个儿子 x x x来进行转移:
l i = m a x { l i , l x , h i + h x } h i = m a x { h i , h x + a x } l_i=max\{ l_i,l_x,h_i+h_x \} \\ h_i=max\{h_i,h_x+a_x\} li​=max{li​,lx​,hi​+hx​}hi​=max{hi​,hx​+ax​}
这样,每次换完根之后再将原来的值还原回去,就可以实现换根dp求解了。

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#define time chrono::system_clock::now().time_since_epoch().count()
#include<ext/pb_ds/tree_policy.hpp>
#define clean(x) memset(x,0,sizeof(x))
#define fil(x,n) fill(x,x+1+n,0)
#define inf 2000000009
#define maxn 1000005
using namespace std;
using namespace __gnu_pbds;
mt19937_64 rnd(time);
cc_hash_table<int,int>mp;int read() {int x=1,res=0;char c=getchar();while(c<'0'||c>'9') {if(c=='-') x=-1;c=getchar();}while(c>='0'&&c<='9') {res=res*10+(c-'0');c=getchar();}return res*x;
}signed main()
{int n=read();int ans=0;vector<int>a(n+1),h(n+1),l(n+1);vector<vector<int>>g(n+1);function<void(int,int)>dfs1=[&](int x,int fa) {h[x]=a[x];l[x]=a[x];vector<int>son_h;for(int i:g[x]) {if(i==fa) continue;dfs1(i,x);h[x]=max(h[i]+a[x],h[x]);son_h.push_back(h[i]);}son_h.push_back(0);sort(son_h.rbegin(),son_h.rend());for(int i:g[x]) {if(i==fa) continue;l[x]=max({l[x],l[i],son_h[0]+son_h[1]+a[x]});}};function<void(int,int)>dfs2=[&](int x,int fa) {vector<int>son_h,son_l; int res=0;for(int i:g[x]) {son_h.push_back(h[i]);son_l.push_back(l[i]);}son_h.push_back(0);son_l.push_back(0);son_h.push_back(0);sort(son_h.rbegin(),son_h.rend());sort(son_l.rbegin(),son_l.rend());for(int i=0;i<min(4,(int)son_h.size());i++) res+=son_h[i]; ans=max(ans,res);for(int i:g[x]) {if(i==fa) continue;int pre_x,pre_i,pre_lx,pre_li;pre_x=h[x];pre_i=h[i];pre_lx=l[x];pre_li=l[i];l[x]=a[x];if(l[i]==son_l[0]) l[x]=max(l[x],son_l[1]);else l[x]=max(l[x],son_l[0]);if(son_h[0]==h[i]) h[x]=son_h[1]+a[x];else h[x]=son_h[0]+a[x];if(son_h[0]==h[i]) l[x]=max(l[x],son_h[1]+son_h[2]+a[x]);else if(son_h[1]==h[i]) l[x]=max(l[x],son_h[0]+son_h[2]+a[x]);else l[x]=max(l[x],son_h[0]+son_h[1]+a[x]);ans=max(ans,l[x]+l[i]);l[i]=max({l[i],l[x],h[x]+h[i]});h[i]=max(h[x]+a[i],h[i]);dfs2(i,x);h[x]=pre_x;h[i]=pre_i;l[x]=pre_lx;l[i]=pre_li;}};for(int i=1;i<=n;i++) a[i]=read();for(int i=1;i<n;i++) {int aa=read(),bb=read();g[aa].push_back(bb);g[bb].push_back(aa);}if(n==1) {puts("0");return 0;}dfs1(1,0);dfs2(1,0);cout<<ans<<endl;return 0;
}

J. Permutation Puzzle

题目大意:构造出一个长度为 n n n排列,使得这个排列满足 m m m个形如 a u < a v a_u<a_v au​<av​的大小关系限制,并且初始有已经填入的数字。

题解:对于形如 a u < a v a_u<a_v au​<av​的关系,我们很容易联系到拓扑排序的性质,我们可以通过建立正向图来进行拓扑排序求解每个位置最小的可能数字 l i l_i li​,通过建立反向图求解每个位置最大的可能数字 r i r_i ri​,然后问题就转化为区间和点的覆盖问题,可以通过优先队列来实现,具体地,将区间按照左端点排序,然后从小到大枚举需要填的数字,每次加入比当前值小的区间,然后用优先队列维护右端点最小的区间作为这个数字应该填入的区间。

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#define time chrono::system_clock::now().time_since_epoch().count()
#include<ext/pb_ds/tree_policy.hpp>
#define inf 2000000009
#define maxn 1000005
#define int long long
using namespace std;
using namespace __gnu_pbds;
mt19937_64 rnd(time);
cc_hash_table<int,int>mp;int read() {int x=1,res=0;char c=getchar();while(c<'0'||c>'9') {if(c=='-') x=-1;c=getchar();}while(c>='0'&&c<='9') {res=res*10+(c-'0');c=getchar();}return res*x;
}void solve() {int n=read(),m=read();int ok=1;vector<int>a(n+1),l(n+1,-1),r(n+1,1e9),de1(n+1),de2(n+1);vector<vector<int>>g1(n+1),g2(n+1);for(int i=1;i<=n;i++) {a[i]=read();if(a[i]!=0) l[i]=r[i]=a[i];} for(int i=1;i<=m;i++) {int aa=read(),bb=read(); //aa->bb;g1[aa].push_back(bb);g2[bb].push_back(aa);de1[bb]++;de2[aa]++;}//g1:cal_L   g2:cal_Rauto topo1=[&]() {queue<int>q;for(int i=1;i<=n;i++) {if(de1[i]==0) {q.push(i);if(a[i]==0) l[i]=1;} }while(q.size()) {int u=q.front();q.pop();for(int i:g1[u]) {int res=l[u]+1;if(res>n) {ok=0;return;};if(a[i]!=0&&a[i]<res) {ok=0;return;}else if(a[i]!=0) l[i]=a[i];else l[i]=max(l[i],res);de1[i]--;if(de1[i]==0) q.push(i);}}};auto topo2=[&]() {queue<int>q;for(int i=1;i<=n;i++) {if(de2[i]==0) {q.push(i);if(a[i]==0) r[i]=n;} }while(q.size()) {int u=q.front();q.pop();for(int i:g2[u]) {int res=r[u]-1;if(res<1) {ok=0;return;};if(a[i]!=0&&a[i]>res) {ok=0;return;}else if(a[i]!=0) r[i]=a[i];else r[i]=min(r[i],res);de2[i]--;if(de2[i]==0) q.push(i);}}};topo1();topo2();vector<array<int,3>>g(n+1);vector<int>ans(n+1);for(int i=1;i<=n;i++) {g[i]={l[i],r[i],i};if(r[i]<l[i]) ok=0;}sort(g.begin()+1,g.end());priority_queue<pair<int,int>>q;int lt=1;for(int i=1;i<=n;i++) {while(lt<=n) {if(g[lt][0]==i) q.push({-g[lt][1],g[lt][2]});else break;lt++;}if(q.size()==0) {ok=0;break;}auto [val,id]=q.top();q.pop();if(i<=-val) ans[id]=i;else ok=0;}if(!ok) {puts("-1");return;}for(int i=1;i<=n;i++) cout<<ans[i]<<" ";puts("");
}signed main()
{int t=read();while(t--) solve();return 0;
}

K. Barrel Theory

题目大意:构造长度为 n n n的正整数序列使得和为 m m m,并且序列的异或和要严格小于最小值。
题解:首先可以看出, n = 1 n=1 n=1时,一定无解。
然后, n = 2 n=2 n=2时,如果 m + 1 2 \frac{m+1}2 2m+1​和 m 2 \frac{m}2 2m​不能满足条件,就一定无解,否则就可以这样构造。
对于 n = 3 n=3 n=3的情况可以打表发现其中如果 m > 19 m>19 m>19就一定有解,并且其中的某一个数字不会超过7,因此我们就可以对于 n = 3 n=3 n=3的情况,暴力枚举所有可能即可。
对于 n > 3 n>3 n>3的情况,可以分成以下四类:

  1. n n n为偶数, m m m为偶数:
    构造(1,1,1,1……),(m-n+2)/2,(m-n+2)/2。
  2. n n n为奇数, m m m为偶数(需要满足 m > n + 2 m>n+2 m>n+2):
    构造(1,2,3),(1,1,1,1……),(m-n-1)/2,(m-n-1)/2
  3. n n n为偶数, m m m为奇数(需要满足 m > 2 n m>2n m>2n):
    构造(2,3),(2,2,2,2……),(m-2n+3)/2,(m-2n+3)/2
  4. n n n为奇数, m m m为奇数(需要满足 m > 2 n + 6 m>2n+6 m>2n+6):
    构造(4,7,2),(2,2,2,2……),(m-2n-3)/2,(m-2n-3)/2
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#define time chrono::system_clock::now().time_since_epoch().count()
#include<ext/pb_ds/tree_policy.hpp>
#define clean(x) memset(x,0,sizeof(x))
#define fil(x,n) fill(x,x+1+n,0)
#define inf 2000000009
#define maxn 2000005
using namespace std;
using namespace __gnu_pbds;
mt19937_64 rnd(time);
cc_hash_table<int,int>mp;int read() {int x=1,res=0;char c=getchar();while(c<'0'||c>'9') {if(c=='-') x=-1;c=getchar();}while(c>='0'&&c<='9') {res=res*10+(c-'0');c=getchar();}return res*x;
}vector<int>ans;
int check(int n,int m) {int x,y,pd=0;if(n==2) { //n=2x=(m+1)/2;y=m/2;if((x^y)<min(x,y)) pd=1;ans.push_back(x);ans.push_back(y);} else if(n==3) { //n=3for(int x=1;x<=m/3;x++) {for(int y=x;y<=(m-x)/2;y++) {int z=m-x-y;if((x^y^z)<min({x,y,z})) {pd=1;ans.push_back(x);ans.push_back(y);ans.push_back(z);break;}}if(pd) break;}}else { //n>3pd=1;if(n%2==0&&m%2==0) {for(int i=1;i<=n-2;i++) ans.push_back(1);ans.push_back((m-n+2)/2);ans.push_back((m-n+2)/2);}else if(n%2==0&&m%2==1) {for(int i=2;i<=3;i++) ans.push_back(i);for(int i=1;i<=n-4;i++) ans.push_back(2);for(int i=1;i<=2;i++) ans.push_back((m-2*n+3)/2);}else if(n%2==1&&m%2==0) {for(int i=1;i<=3;i++) ans.push_back(i);for(int i=1;i<=n-5;i++) ans.push_back(1);ans.push_back((m-n-1)/2);ans.push_back((m-n-1)/2);}else if(n%2==1&&m%2==1) {for(int i=1;i<=n-4;i++) ans.push_back(2);ans.push_back(4);ans.push_back(7);ans.push_back((m-2*n-3)/2);ans.push_back((m-2*n-3)/2);}}return pd;
}void solve() {ans.clear();int n=read(),m=read();if(n==1||m==n+1) {puts("NO");}else if((m<2*n&&m%2==1)||(n%2==1&&m<2*n+7&&m%2==1)) {puts("NO");}else {if(!check(n,m)) puts("NO");else {cout<<"YES\n";for(int i:ans) cout<<i<<" ";puts("");}}
}signed main()
{int t=read();while(t--) solve();return 0;
}

B. Code With No Forces

题目大意:给定 m m m个提交, n n n个测试数据,问最少剩下多少个测试数据,能够保证测试结果与原先的测试结果保持一致。
题解:对于每一个题解分别维护三个量:是否终止,空间达到要求,时间达到要求。对于答案正确的提交,即使已经终止也可以继续接受测试数据,对于答案错误的提交,一旦终止就不能继续接受测试数据。最终,取所有可行的结果也就是所有提交都已经终止的结果中,所需测试数据最少的结果即可。
可以采用记忆化搜索实现,采用状态压缩的方法存储所有提交的状态,转移的时候注意讨论清楚即可。

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#define time chrono::system_clock::now().time_since_epoch().count()
// #include<ext/pb_ds/tree_policy.hpp>
#define clean(x) memset(x,0,sizeof(x))
#define fil(x,n) fill(x,x+1+n,0)
#define inf 2000000009
#define maxn 2000005
using namespace std;
using namespace __gnu_pbds;
mt19937_64 rnd(time);
cc_hash_table<int,int>mp;int read() {int x=1,res=0;char c=getchar();while(c<'0'||c>'9') {if(c=='-') x=-1;c=getchar();}while(c>='0'&&c<='9') {res=res*10+(c-'0');c=getchar();}return res*x;
}struct node {int type,Time,memory;char c1,c2;
};int cal_type(char c1,char c2) {if(c1=='O'&&c2=='K') return 1;if(c1=='W'&&c2=='A') return 2;if(c1=='T'&&c2=='L') return 3;if(c1=='M'&&c2=='L') return 4;else return 5;
}int cal(int to,int j,int i) {if( to&( 1<<( (j-1)*3+i ) ) ) return 1;else return 0;
}void print(int x) {stack<int>s;for(int i=9;i>=0;i--) {if(x&(1<<i)) cout<<1;else cout<<0;}
}struct nn {int val;vector<int>ans;
};
nn f[maxn];signed main()
{int n,m;cin>>n>>m;vector data(n+1,vector<node>(m+1));vector<int>end(m+1),ac(m+1),ti(m+1),me(m+1),tp(m+1);for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {char c1,c2;int tim,mem;cin>>c1>>c2;scanf(",%d/%d",&tim,&mem);data[i][j].type=cal_type(c1,c2);data[i][j].Time=tim;data[i][j].memory=mem;if(end[j]!=0) continue;ti[j]=max(ti[j],data[i][j].Time);me[j]=max(me[j],data[i][j].memory);tp[j]=cal_type(c1,c2);if(data[i][j].type!=1) end[j]=1;}}// puts("111");int tot=(1<<(3*m))-1;for(int i=1;i<=m;i++) if(end[i]==0) ac[i]=1;auto dfs=[&](auto dfs,int x) {vector<int>ans;if(x==tot) return (nn){0,ans};if(f[x].val!=0) return f[x];int res=2e9;for(int i=1;i<=n;i++) {int pd=1;int to=x;for(int j=1;j<=m;j++) {if( (x>>((j-1)*3))&1 ) continue; //endif(data[i][j].type!=1&&data[i][j].type!=tp[j]) pd=0;if(data[i][j].Time>ti[j]) pd=0;if(data[i][j].memory>me[j]) pd=0;if(data[i][j].Time==ti[j]) to|=1<<((j-1)*3+1);if(data[i][j].memory==me[j]) to|=1<<((j-1)*3+2);if(data[i][j].type==tp[j]&&cal(to,j,1)&&cal(to,j,2))to|=1<<((j-1)*3);else if(data[i][j].type==tp[j]&&tp[j]!=1) pd=0;}if(to==x) continue;if(pd==0) continue;nn u=dfs(dfs,to);if(u.val+1<res) {res=u.val+1;ans=u.ans;ans.push_back(i);}}if(res<2e9) f[x]=(nn){res,ans}; return (nn){res,ans};};nn u=dfs(dfs,0);cout<<u.val<<endl;for(int i=u.ans.size()-1;i>=0;i--) {cout<<u.ans[i]<<" ";}return 0;
}

CCPC2022(桂林)相关推荐

  1. CCPC2022桂林 M. Youth Finale (gym104008M)

    Problem - M - Codeforces 题目大意:给出一个长度为n的排列a和m次操作,有两种操作,操作S使a1移到最右边,操作R使数组倒置,问初始数组和每次操作后逆序对的数量 1<=n ...

  2. 东大漆桂林、清华李涓子、复旦肖仰华等大牛确认出席CTA峰会!5月一起打卡杭州...

    5月26日-27日,由中国IT社区CSDN与数字经济人才发展中心联合主办的第一届CTA核心技术及应用峰会将在杭州国际博览中心召开. 首届CTA核心技术及应用峰会将聚焦人工智能,邀请技术领航者,与开发者 ...

  3. 桂林机场春运期间新增多条航线航班 实现接力承运无缝衔接

    中新网桂林1月17日电(钟楚雄)桂林两江国际机场服务营销部介绍,桂林机场协调多家航空公司,在2019年春运期间增加运力,新增多条航线航班,满足旅客探亲.访友.旅游等出行需求. 吉祥航空将于2019年1 ...

  4. 手机超广角拍摄软件_桂林好的拍摄短视频手机软件

    桂林好的拍摄短视频手机软件 F1j0c1m9 桂林好的拍摄短视频手机软件 因此一个谨慎的文案策划,可以很大程度上保证后期制作流程的稳健运行.很多时候为了更好的宣传一款产品都会选择制作产品广告片,它可以 ...

  5. 桂林哪些职校可以学计算机,桂林市有几个中等职业学校

    全州县职教中心学校坐落于"桂北明珠"之称的全州县才湾镇小坪里,地理位置优越,交通便利,湘桂铁路.衡昆高速公路.国道322线贯穿东北西南,途经学校门口.学校土地辽阔,占地2360亩, ...

  6. 2021全州高中高考成绩查询,最新!最全!桂林各中学高考成绩汇总!为桂林考生骄傲!...

    原标题:最新!最全!桂林各中学高考成绩汇总!为桂林考生骄傲!随着2019年高考成绩相继公布,桂林不少中学陆续传来喜报,一起来看看你的母校今年成绩如何? 广西师范大学附属外国语学校 1.广西文.理总分前 ...

  7. 桂林电子科技大学 计算机学院,桂林电子科技大学信息科技学院

    出国留学网高考网为大家提供2016桂林电子科技大学信息科技学院招生章程,更多高考招生简章请关注我们网站的更新! 2016桂林电子科技大学信息科技学院招生章程 一.学院概况 桂林电子科技大学信息科技学院 ...

  8. 桂林电子科技大学计算机导论,Welcome to Guilin University of Electronic Technology(桂林电子科技大学)...

    Welcome to Guilin University of Electronic Technology(桂林电子科技大学) Located in scenic Guilin, a world-fa ...

  9. c语言实验答案周信东第三章,桂林电子科技大学C语言程序设计习题答案周信东实验顺序结构与逻辑运算.pdf...

    桂林电子科技大学C语言程序设计习题答案周信东实验顺序结构与逻辑运算.pdf 成 绩 良 评 语 继 续 努 力 . 批 改 时 间 2013-11-16 105155 批 改 老 师 实 验 2 顺 ...

最新文章

  1. Hexo集成Algolia实现搜索功能
  2. mysql 必须掌握的工具pt-query-digest安装
  3. Ubuntu:Ubuntu下安装Anaconda和Tensorflow的简介、入门、安装流程之详细攻略
  4. 电脑上怎么配置mysql数据库服务器_Mysql数据库服务器安装与配置详解教程
  5. python3异步协程爬虫,simpyder
  6. cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration的解决
  7. 如何解决未经检查的演员表警告?
  8. 【UVA10652】Board Wrapping(凸包+坐标旋转+多边形面积)
  9. 【Pytorch-手写字体识别】手写字体识别项目
  10. 最新版 INSPINIA IN+ - WebApp Admin Theme v2.7.1,包含asp.net MVC5示例代码,做管理系统最佳的选择。...
  11. 基于Python的西瓜数据集 3.0α的SVM实现
  12. 机器学习——概率论基础
  13. 感性电路电流计算_电路分析基础(10)-电路以及信号的功率和能量
  14. 今天睡眠质量记录88分
  15. jhipster使用liquibase修改一个表的一个字段
  16. 知识欠缺到沙漠化了吧
  17. 常见的注册表修改大全
  18. 《Redis设计与实现 黄建宏 著》阅读笔记目录(持续更新)
  19. Android系统VIN码识别SDK
  20. UOS系统适配-常用开发工具安装

热门文章

  1. MySQL日志发送syslog_syslog详解及配置远程发送日志和远程日志分类
  2. 谷歌地图高清卫星地图下载免费
  3. SVM函数间隔和几何间隔
  4. CentOS安装教程
  5. dat模板文件读取的Python脚本
  6. Nature综述:人类微生物培养以及培养组学(Culturing the human microbiota and culturomics)
  7. 《低代码指南 》100解决方案——1面对经销商赊销,企业该如何规避应收账款风险?
  8. 如何培养优秀的销售人员?
  9. 南京师范大学地信/GIS/地图学与地理信息系统考研经验
  10. STM32驱动OV7670(无FIFO)相关问题的解决