查看题目


A 黑色气球

题意:

n个气球,每个气球高度为正整数。给你每两个气球之间的高度和,还原出所有气球的高度,保证答案唯一。

解题思路:

签到题,因为高度的范围不大,直接枚举第一个气球的高度,检测其与第二,三个气球的关系是否合法。需注意因为答案唯一所以只有两个气球的时候高度肯定都为1.

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define inf 1000000000
#define Inf 223372036854775807
#define maxn 1005
using namespace std;
typedef long long ll;
const ll mod=998244353;
const double eps=1e-9;
const double PI=acos(-1.0);int n, num[maxn], s[maxn][maxn], x;int main()
{cin>>n;for (int i=1; i<=n; i++)for (int j=1; j<=n; j++)cin>>s[i][j];for (x=1; x<=100000; x++)if (s[1][2]-x+s[1][3]-x==s[2][3]) break;if (n==2) x=1;for (int i=1; i<=n; i++)cout<<abs(s[1][i]-x)<<" ";return 0;
}

C 无向图定向

题意:

给一个n个点m条边的无向图,要求你对每条边指定一个方向,使原图成为一个有向无环图,且最长路最短,输出最短的最长路。

解题思路:

有个结论,给点染色,有边直接相连的点颜色不能一样,然后答案就是最少染色数-1。
所以用状压dp或者直接深搜找出无向图的最少染色数就行了。
关于结论的证明:其本质就是“狄尔沃斯定理”,定理指出:对于任意有限偏序集,其最长链中元素的数目必等于其最小反链划分中反链的数目。
狄尔沃斯定理的证明可以自行百度。

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define inf 1000000000
#define Inf 223372036854775807
#define maxn 1005
using namespace std;
typedef long long ll;
const ll mod=998244353;
const double eps=1e-9;
const double PI=acos(-1.0);vector<int> edge[maxn];
int n, m, ans=inf, col[maxn];int check(int now, int c)
{for (auto to: edge[now])if (c==col[to]) return 0;return 1;
}void dfs(int now, int res)
{if (now>n) {ans=min(res, ans); return ;}if (res>=ans) return ;for (int i=1; i<=res+1; i++){if (!check(now, i)) continue;col[now]=i;if (i==res+1){res++;dfs(now+1, res);res--;}else dfs(now+1, res);col[now]=0;}
}int main()
{cin>>n>>m;for (int i=1, u, v; i<=m; i++){cin>>u>>v;edge[u].push_back(v);edge[v].push_back(u);}dfs(1, 0);cout<<ans-1;return 0;
}

E 棋技哥

题意:

两人下棋,棋盘大小为n*m,每个格子要么是黑色的要么是白色的。两人轮流操作,操作者可以选择一个黑色格子,并将以其为右下角,棋盘左上角为左上角的矩形中的所有格子颜色翻转,若无黑格可选,则当前操作者输。问先手者会赢还是输。

解题思路:

签到+大力猜测题。由于每次翻转都会导致棋盘左上角被翻转,因此若左上角开局是黑色的,后手者操作完左上角一定还是黑色的,因此先手者一定胜。若为白则先手者操作完左上角一定为黑,则后手者必胜。所以直接判断左上角颜色就行了。

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
#define inf 1e9+1
#define Inf 223372036854775807
#define maxn 1010
#define eps 1e-8
const ll mod=998244353;string s[maxn];
int T, n, m;int main()
{cin>>T;while (T--){cin>>n>>m;for (int i=1; i<=n; i++)cin>>s[i];if (s[1][0]=='1') cout<<"call\n";else cout<<"aoligei\n";}return 0;
}

F 社团管理

题意:

有n个人站成一排,第i个人有一个权值ai,要把他们分成恰好k段并使每段内两两权值相同的对数之和最少。

解题思路:

决策单调性+整体二分转移+莫队
超出能力范围了,不是很清楚这样写算不算有点套路的东西?反正确实是想不到…
决策单调性的证明可以看这位大佬的博客
总的来说,发现决策单调性后就可以通过类似整体二分的方法。
假设最优转移点的区间是[L, R],寻找[l, r]区间内每个点的最优转移点时可以先寻找到区间中点mid的最优转移点p,然后区间内左半段的点的最优转移点肯定在[L, p],右半段的点的最优转移点肯定在[p+1, R]。然后答案的统计利用莫队的思想来实现。
具体可以看代码吧,感觉对这道题解法的理解还有待加深。

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define inf 1000000000
#define Inf 223372036854775807
#define maxn 100010
using namespace std;
typedef long long ll;
const ll mod=998244353;
const double eps=1e-9;
const double PI=acos(-1.0);ll cnt[maxn], num[maxn], ans;
ll lp=1, rp=0, dp[21][maxn];
ll n, k;void add(ll x)
{ans+=cnt[x];cnt[x]++;
}
void red(ll x)
{cnt[x]--;ans-=cnt[x];
}
void md(int l, int r)
{while (lp>l) add(num[--lp]);while (lp<l) red(num[lp++]);while (rp>r) red(num[rp--]);while (rp<r) add(num[++rp]);
}
void cal(int l, int r, int L, int R, int k)
{if (l>=r){for (int i=L; i<=R; i++){md(i, l);if (dp[k][l]>dp[k-1][i-1]+ans)dp[k][l]=dp[k-1][i-1]+ans;}return ;}int mid=(l+r)>>1, p=L;for (int i=L; i<=min(R, mid); i++){md(i, mid);if (dp[k][mid]>dp[k-1][i-1]+ans)dp[k][mid]=dp[k-1][i-1]+ans, p=i;}cal(l, mid, L, p, k);cal(mid+1, r, p, R, k);
}int main()
{cin>>n>>k;for (int i=1; i<=n; i++)cin>>num[i];memset(dp, 0x3f, sizeof(dp));for (int i=1; i<=n; i++){add(num[++rp]);dp[1][i]=ans;}for (int i=2; i<=k; i++){dp[i][0]=0;cal(1, n, 1, n, i);}cout<<dp[k][n];return 0;
}

G 火山哥周游世界

题意:

给一颗n个节点的树,其中有k个节点是需要到达的,求分别以1,2…n为起点时经过k个节点的路径长度(不需要回到起点)。

解题思路:

从简考虑,假设没有k这个条件,每个点都要求到达的情况。
假设起点固定,比如说1号点为起点,要求出此时的答案,稍加观察就可以发现,最优情况下应该是从1号点到以1为根的树中最深点的路径上的边走一遍,其它边走两遍,这个最多动手画一下就能感受出来。
也就是1号点的答案就是所有边长度和乘2再减去最深点的深度。对其它点也是如此,因此我们只要能找到以i号点为根的情况下最深点的深度,就可以求出答案。
如果我们先求出了一号点的答案,并且记录了各个点在以一号点为根的情况下的深度,我们就可以对答案进行转移。
稍加观察可以发现,点的最深路径可以转移给它的儿子。
第一种情况:如果这个儿子不在其父亲到最深点的路径上,那么以这个点为根时最深点一定仍是原来那个点(因为最深的路径又加上了一条边)。
第二种情况:如果这个儿子在其父亲到最深点的路径上,那么就需要判断之前的最深路径是否还是最深的(因为少了一条边),具体而言,我们除了要记录每个点往下最深点,还要记录次深点。
第二种情况可以参考下图,当由fi转移到i时最深路径的三种情况。

现在再加入k这个条件,不难发现如果我们先找出这k个点的“虚树”(这里可能不能叫虚树,应该是包含了这k个点以及他们之间两两路径的树),其它点的答案就等于其到“虚树”最近距离的点的答案加上两者之间的距离。
(实现过程:大力dfs

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
#define inf 1e9+1
#define Inf 223372036854775807
#define maxn 501000
#define eps 1e-8
const ll mod=998244353;struct bian
{ll to, v;
};ll n, K, root, go[maxn], col[maxn], ans[maxn];
vector<bian> E[maxn], edge[maxn];
ll sdp[maxn], mxdp[maxn], sedp[maxn], mxdpt[maxn];ll dfs(ll now, ll fa)
{//找出“虚树”,建边ll f=0;if (go[now]) f=1;for (auto i: E[now]){if (i.to==fa) continue;if (dfs(i.to, now)){f=1;edge[now].push_back((bian){i.to, i.v});edge[i.to].push_back((bian){now, i.v});}}if (f) go[now]=1;return f;
}void dfs2(ll now, ll fa)
{//找出 不在虚树上的点 的 虚树上最近的点 是哪个if (go[now]) col[now]=now;for (auto i: E[now]){if (i.to==fa) continue;if (!go[i.to]){ans[i.to]=ans[now]+i.v;col[i.to]=col[now];}dfs2(i.to, now);}
}void dfs3(ll now, ll fa)
{for (auto i: edge[now]){if (i.to==fa) continue;dfs3(i.to, now);sdp[now]+=sdp[i.to]+i.v;if (mxdp[i.to]+i.v>mxdp[now])sedp[now]=mxdp[now], mxdp[now]=mxdp[i.to]+i.v, mxdpt[now]=i.to;else if (mxdp[i.to]+i.v>sedp[now]) sedp[now]=mxdp[i.to]+i.v;}
}void dfs4(ll now, ll fa)
{ans[now]=-mxdp[now];for (auto i: edge[now]){if (i.to==fa) continue;if (i.to!=mxdpt[now]){mxdpt[i.to]=now;mxdp[i.to]=mxdp[now]+i.v;dfs4(i.to, now);continue;}if (sedp[now]+i.v>sedp[i.to]) sedp[i.to]=sedp[now]+i.v;if (i.to==mxdpt[now]){if (mxdp[i.to]<=sedp[i.to]){mxdpt[i.to]=now;mxdp[i.to]=sedp[i.to];dfs4(i.to, now);}else{dfs4(i.to, now);}}}
}int main()
{cin>>n>>K;for (ll i=1, u, v, w; i<n; i++){cin>>u>>v>>w;E[u].push_back((bian){v, w});E[v].push_back((bian){u, w});}for (ll i=1, x; i<=K; i++){cin>>x;go[x]=1;root=x;}dfs(root, 0);dfs2(root, 0);dfs3(root, 0);ans[root]=-mxdp[root];dfs4(root, 0);for (ll i=1; i<=n; i++){if (go[i]) cout<<2*sdp[root]+ans[i]<<"\n";else cout<<ans[i]+2*sdp[root]+ans[col[i]]<<"\n";}return 0;
}

2020 CCPC Wannafly Winter Camp Day3 部分题解(ACEFG)相关推荐

  1. 阔力梯的树(2020 CCPC Wannafly Winter Camp Day2 Div.12 )dsu on tree

    题解: dsu on tree dsu on tree的基本步骤就不说了 看到这题询问结点的子树问题,而且询问时离线的,首先想到的dsu on tree的这个trick. 本题的难题就是如何维护结点所 ...

  2. 2020 CCPC Wannafly Winter Camp Day2 Div.12——A 托米的字符串【构造、数学】

    题目传送门 题目描述 托米有一个字符串,他经常拿出来玩.这天在英语课上,他学习了元音字母 a , e , i , o , u {a,e,i,o,u} a,e,i,o,u 以及半元音 y {y} y . ...

  3. 2020 CCPC Wannafly Winter Camp Day6 M—自闭——模拟

    链接:https://ac.nowcoder.com/acm/contest/4137/M 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...

  4. 2020 CCPC Wannafly Winter Camp Day7 K 修炼

    题意: 一个游戏,规则如下: 有六个值 v 1 , v 2 , a 1 , a 2 , b 1 , b 2 v_1,v_2,a_1,a_2,b_1,b_2 v1​,v2​,a1​,a2​,b1​,b2 ...

  5. 2019 wannafly winter camp day5-8代码库

    目录 day5 5H div2 Nested Tree (树形dp) 5F div2 Kropki (状压dp) 5J div1 Special Judge (计算几何) 5I div1 Sortin ...

  6. CCPC-Wannafly Winter Camp Day3 (Div2, onsite) I 石头剪刀布(按秩合并并查集)

    题解:每次有两个事件: y y去挑战xx,如果赢了可以坐在x x的位置,打平或者输了就要被淘汰. 询问在进行所有一类事件后,有多少种情况可以让x x现在还没有被淘汰. 对于第二类事件,我们假设x x挑 ...

  7. Wannafly Winter Camp Day 3 G排列(贪心)

    思路来源 jls%%% 题解 赛后补队友AC的水题可还行 最先出现的单减子序列对应的位置,一定是那些最小值的位置 先把那些放满,剩下的贪心选使字典序最小,就把剩下的从前到后扫一遍从小到大放 代码 #i ...

  8. 2019 CCPC wannfly winter camp Day 5

    C - Division 思路:我们考虑到一点,从大往小取得顺序是不会有问题的,所以可以直接主席树,但是开不下空间,我们可以log分段求. #include<bits/stdc++.h> ...

  9. 2019 CCPC wannfly winter camp Day 8

    E - Souls-like Game 直接线段树合并矩阵会被卡T掉,因为修改的复杂度比询问的复杂度多一个log,所以我们考虑优化修改. 修改的瓶颈在于打lazy的时候, 所以我们预处理出每个修改矩阵 ...

最新文章

  1. python中词云图怎样变成特殊图案_如何利用python画出一个多变的词云图?(1)...
  2. python编程制作接金币游戏,闪电侠接金币的FlashMan类
  3. python随机森林 交叉验证_随机森林是否需要交叉验证+特征的重要性
  4. linux基础-权限管理,手工添加用户,umask,bash配置文件
  5. python 批量重命名文件_Python批量重命名文件的方法
  6. DB2百度网盘下载的地址
  7. 用opencv方法遍历文件夹图片(比较清晰)
  8. 基于JAVA实现的图形化页面置换算法
  9. drcom for linux,Ubuntu Linux 6.10下用Dr.COM(drcom-client)接入网络的问题
  10. On the burstiness of visual elements
  11. Pandas读取数据
  12. MicroStrain 3DM-GX3-25 ROS 开发
  13. Python爬取百度指数搜索结果,查看你想了解的热点信息吧
  14. Scrum Master: 应做和不应做的事情
  15. mbedtls 连接 阿里云物联网
  16. Android音频——音量调节
  17. 今天终于知道了什么是X-window中字体hinting的含义了!
  18. html那些标签可以实现页面布局,网页的布局一般用什么来实现
  19. 川教版计算机三年级下册教案,三年级下册川教版信息技术教案
  20. 为何我总能在闹钟响前醒来?

热门文章

  1. 王者荣耀张大仙用计算机,同样是玩王者荣耀张大仙用手机, 嗨氏用模拟器, 哪个更简单容易?...
  2. 酒鬼私定,只是酒鬼酒一次破圈营销?
  3. 姓祝男孩名字简单大气
  4. 斗鱼 H5 直播原理解析,它是如何省了 80% 的 CDN 流量?
  5. 手机制式如何理解(来自百度知道)
  6. linux分区文件ext4和ext3,Windows下读取Linux的ext3/ext4格式分区
  7. 前端数组删除元素字典操作
  8. 判断数独是否成功(c++)
  9. 安卓平板隐藏虚拟按键_Android实现隐藏手机底部虚拟按键
  10. 佛语66句话,震撼你的内心世界