题目链接:
I题修改
题解:
比较巧妙的转换成图论的好题,思路感觉不太好像,不过感觉是个经典题(
雾) 。因为初始的序列是随机,不妨假设序列的每一位的数都不一样,即最复杂的情况。
然后我们考虑这个操作的意义,第i次操作其实就是把的值变成的值,
我们可以建一个虚点a[n+1]=0。
这样操作就变成了在 和 建一条权值为 的边,具体的含义上面解释过了。
这样最终的答案不就是求我们建的图的最小生成树的权值和。。
代码:
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (int i = (s); i <= (t); i++) #define RP(i,t,s) for (int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define debug puts("ac") #define INF 0x3f3f3f3f #define LINF 0x3f3f3f3f3f3f3f3f using namespace std; inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 2e5+7; struct edge{ int u,v,w; }e[N]; int fa[N]; int find(int x){ return x==fa[x]?fa[x]:fa[x]=find(fa[x]); } bool cmp(edge a,edge b){ return a.w<b.w; } int main(){ int n=read(),m=read(); rp(i,1,m) e[i].u=read(),e[i].v=read()+1,e[i].w=read(); rp(i,1,n+1) fa[i]=i; sort(e+1,e+1+m,cmp); ll ans=0; int cnt=0; rp(i,1,m){ int u=find(e[i].u),v=find(e[i].v); if(cnt==n) break; if(u!=v){ cnt++; ans+=e[i].w; fa[u]=fa[v]; } } if(cnt!=n) cout<<-1<<endl; else cout<<ans<<endl; return 0; }
J题克隆
题解:因为最终要保证点至少被经过一次,而且给的 这个数很有特点,我们用它乘以k不难发现>=2n的,即这k个人走过的点数和>=2n。
这时我们就需要知道一个知识,一个图的欧拉序的点数和是满足这个条件的(注意这里说的是第二种欧拉序,如果不懂得话可以参考这篇文章)。
因此我们只需要求欧拉序,然后不断的连续取 的点就是符合条件的了,因为欧拉序本身就能保证连续区间的点彼此也都是可以连续的。
代码:
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (int i = (s); i <= (t); i++) #define RP(i,t,s) for (int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define debug puts("ac") #define INF 0x3f3f3f3f #define LINF 0x3f3f3f3f3f3f3f3f using namespace std; inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } const int N = 1e5+7; vector<int> G[N]; int vis[N]; vector<int> ans; void dfs(int u){ ans.p_b(u); vis[u]=1; for(auto v:G[u]){ if(vis[v]==1) continue; dfs(v); ans.p_b(u); } } int main(){ int n=read(),m=read(),k=read(); rp(i,1,m) { int u=read(),v=read(); G[u].p_b(v); G[v].p_b(u); } dfs(1); puts("YES"); int num=(2*n+k-1)/k; int len=ans.size(); int cur=0; rp(i,1,k){ int tmp=min(cur+num-1,len-1); if(cur>len-1) puts("1 1"); printf("%d ",tmp-cur+1); rp(j,cur,tmp) printf("%d ",ans[j]); puts(""); cur=tmp+1; } return 0; }
D题
题解:这个题的数据有点弱,不知道为啥有的明显错误的方法都给过了。。。。。
正解除了题解中给出的二分(
其实是不理解)做法,另一个做法也是很好理解的。我们推导样例不难发现,最多只能获得深度小于等于操作次数的点的子树节点的min能够在符合条件的max操作里传到根节点。
因此答案就是所有深度小于等于操作次数的子树节点的min值中的最大值。。
#include <bits/stdc++.h> #define PI atan(1.0)*4 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define sc(x) scanf("%d",&x) #define scl(x) scanf("%lld",&x) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define pll pair<ll,ll> #define pil pair<int,ll> #define m_p make_pair #define p_b push_back #define ins insert #define era erase #define debug puts("ac") #define INF 0x3f3f3f3f #define LINF 0x3f3f3f3f3f3f3f3f using namespace std; inline int read(){ int s=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } #define M 200020 int n,m,dep[M],mn[M],val[M],ls[M],rs[M],ans=-INF; inline void dfs(int x,int last=0){ dep[x]=dep[last]+1; if(!ls[x]&&!rs[x]) mn[x]=val[x]; else mn[x]=INF; if(ls[x]) dfs(ls[x],x),mn[x]=min(mn[x],mn[ls[x]]); if(rs[x]) dfs(rs[x],x),mn[x]=min(mn[x],mn[rs[x]]); if(dep[x]<=((m+1)>>1)) ans=max(ans,mn[x]); } int main(){ n=read(),m=(n-1)>>1; for(int i=1;i<=n;i++) ls[i]=read(),rs[i]=read(); for(int i=1;i<=n;i++) val[i]=read(); dep[0]=-1,dfs(1),printf("%d\n",ans); return 0; }