10-8 DAIRY
来源:互联网 发布:截面数据常用模型 编辑:程序博客网 时间:2024/06/14 09:03
前几天没写完的都是要么难以理解要么懒得打题了【工业】
今天也来划水~~~
今天的出题人何爷爷因为太帅(lan)气(duo)了,所以solution…不存在的(tan90°)
【hyy:我什么时候写过solution?】
T1 Graph 0
审题要仔细,做题更要仔细。不要在做题的时候就忘记了题目有两个小问!
很惨的爆0了一道真的就没有什么思考难度的题。
第一问:求最多的次数。
很明显就是每个连通块内边数>>1累加起来。
第二问:所以我就是写代码写着写着不记得要输出方案了。(毕竟是最后才开始写这道题)
也很明显,我们dfs时顺便就把方案记录一下。【完全ojbk…】
满分修改如下:
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>#include<vector>using namespace std;const int N = 100010;const int M = 200010;vector<int> V[N];int n, m, ans, e, cnt;int pre[N], fa[N];int to[M<<1], nxt[M<<1], head[N];template <typename T>T read(){ T N(0), F(1); char C = getchar(); for(; !isdigit(C); C = getchar()) if(C == '-') F = -1; for(; isdigit(C); C = getchar()) N = N*10 + C-48; return N*F;}void add(int u, int v){ to[++e] = v; nxt[e] = head[u]; head[u] = e; to[++e] = u; nxt[e] = head[v]; head[v] = e;}int find(int x){ return x == fa[x] ? x : fa[x] = find(fa[x]); }void dfs(int u, int f = 0){ pre[u] = ++cnt; for(int i = head[u]; i; i = nxt[i]){ int v = to[i]; if(v == f) continue; if(!pre[v]){ fa[v] = u; dfs(v, u); } else if(pre[v] < pre[u]){ V[u].push_back(v); } } if(fa[u]){ if(V[u].size() & 1) V[u].push_back(fa[u]); else V[fa[u]].push_back(u); }}int main(){ freopen("graph.in", "r", stdin); freopen("graph.out","w",stdout); n = read<int>(); m = read<int>(); for(int i = 1; i <= m; i++){ int u = read<int>(); int v = read<int>(); add(u, v); } for(int i = 1; i <= n; i++){ if(!pre[i]) dfs(i); } for(int i = 1; i <= n; i++){ ans += V[i].size() >> 1; } printf("%d\n", ans); for(int i = 1; i <= n; i++){ for(int j = 1; j < V[i].size(); j += 2){ printf("%d %d %d\n", V[i][j-1], i, V[i][j]); } } return 0;}
T2 permutation 50
我也不知道一个完全没有正确性的做法怎么有50分的,但是据说连什么爆搜都搜出了90(笑)
我的考场想法是:
序列从前往后的确定每一个位置的最终数字。其实肯定不是最终的,(非正确做法)但我觉得能水过去一些点吧。这里我是怎么确定的呢,我不是往后>=k位一个个判断的,这样明显浪费时间。因为观察到是一个排列,所以数字和所在位置一定都是1~n的,这样我又开一个数组b[i]记录i这个数字当前所在位置。题目要求数值差==1。故每次只要判断比当前位数值小1的数值在哪个位置,这个位置是否与当前位相差>=k,符合就交换,不符合就视作已达到最终结果。
有一股贪心的味儿(#`O′)
正解我还没怎么弄明白,还是有些难度的。(记不太清hyy的讲解了)这个题思路需要转化一下。题目要求数值差为1,位置差>=k,可以转化为另一序列要求位置差为1,数值差
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>using namespace std;const int oo = 1000007;const int N = 500010;int n, k, x, y, tmp;int a[N], p[N];template <typename T>T read(){ T N(0), F(1); char C = getchar(); for(; !isdigit(C); C = getchar()) if(C == '-') F = -1; for(; isdigit(C); C = getchar()) N = N*10 + C-48; return N*F;}int main(){ freopen("permutation.in", "r", stdin); freopen("permutation.out","w", stdout); n = read<int>(); k = read<int>(); for(int i = 1; i <= n; i++){ a[i] = read<int>(); p[a[i]] = i; } a[0] = oo; for(int i = 1; i <= n; i++){ while(a[p[a[i]-1]] < a[p[a[i]]] && p[a[i]-1] - p[a[i]] >= k){ x = a[i]-1, y = a[i]; a[p[x]] = y; a[p[y]] = x; tmp = p[x]; p[x] = p[y]; p[y] = tmp; } } for(int i = 1; i <= n; i++) printf("%d\n", a[i]); return 0;}
T3 tree 100 国家集训队论问题被众人猜出结论直接秒题,让出题人hyy哭晕在厕所。
这是一道集训队论问题,然而…并不是我能去集训队了,而是this结论题实在太走运了。我写了个5pts暴力打了几组数据发现answer全部是权值和。就大胆猜测,省去证明(不会),直接当作结论题写了两行代码。
莫名其妙A掉了/???
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>using namespace std;typedef long long ll;const int N = 100010;int n;ll ans;template <typename T>T read(){ T N(0), F(1); char C = getchar(); for(; !isdigit(C); C = getchar()) if(C == '-') F = -1; for(; isdigit(C); C = getchar()) N = N*10 + C-48; return N*F;}int main(){ freopen("tree.in", "r", stdin); freopen("tree.out","w",stdout); n = read<int>(); for(int i = 1; i < n; i++){ int u = read<int>(); int v = read<int>(); ll w = read<ll>(); ans += w; } printf("%lld\n", ans); return 0;}
考场写的5pts暴力如下,好像还有点问题,不过用来发现结论绰绰有余了(中间结果什么的没有注释掉,反正是用来找结论的):
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>using namespace std;typedef long long ll;const ll oo = 1e18+7;const int N = 110;ll sum, ans, pn, h;int n, f;int vis[N], p[N], res[N];ll e[N][N], pth[N];template <typename T>T read(){ T N(0), F(1); char C = getchar(); for(; !isdigit(C); C = getchar()) if(C == '-') F = -1; for(; isdigit(C); C = getchar()) N = N*10 + C-48; return N*F;}void dfs(int s, int t){ if(f) return; if(s == t){ f = 1;// for(int i = 1; i <= pn; i++){ sum = min(sum, pth[i]); printf("%lld ", pth[i]);}// printf("\n"); return; } for(int i = 1; i <= n; i++){ if(e[s][i] != -1 && !vis[i]){ vis[i] = 1; pth[++pn] = e[s][i]; dfs(i, t); vis[i] = 0; pn--; } }}int main(){ freopen("tree.in", "r", stdin); freopen("tree.out","w",stdout); n = read<int>(); for(int i = 1; i <= n; i++) p[i] = i; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ e[i][j] = -1; } } for(int i = 1; i < n; i++){ int u = read<int>(); int v = read<int>(); ll w = read<ll>(); e[u][v] = e[v][u] = w; } do{ h = 0LL; for(int i = 1; i < n; i++){ int u = p[i]; int v = p[i+1]; memset(vis, 0, sizeof(vis)); vis[u] = 1; f = pn = 0; sum = oo; dfs(u, v); h += sum; } // printf("%lld\n", h);// ans = max(ans, h); if(ans < h){ for(int i = 1; i <= n; i++) res[i] = p[i]; ans = h; } }while(next_permutation(p+1, p+n+1)); for(int i = 1; i <= n; i++) printf("%d ", res[i]); printf("\n"); printf("%lld\n", ans); return 0;}
证明其实也不难,不好写出来,感性理解一下。
首先显然ans的上界就是权值和,现在要证明ans的下界同样是权值和。
/*
一条边接A、B两点,必定不会从A->B->别的点->B->A->…
在经过A-B这条边前一定会把A那边一堆点包括什么循环回到A的点都走一遍,所以最佳方案不存在又绕回A这样的方案。
*/
我们把边权从小到大考虑,每次考虑一条边的时候,都把这棵树分成左右两棵树(两个子问题),而当前考虑的这条边必定会被经过,所以对答案的贡献必定会被算一次。划分成子问题考虑都是如此,所以每一条边都对答案至少产生一次贡献,所以ans必定是权值和。
- 8-10 DAIRY
- 10-8 DAIRY
- 8-8 DAIRY
- 8-7 DAIRY
- 8-9 DAIRY
- 8-11 DAIRY
- 8-12 DAIRY
- 8-13 DAIRY
- 8-14 DAIRY
- 8-15 DAIRY
- 8-16 DAIRY
- 8-17 DAIRY
- 8-18 DAIRY
- 8-19 DAIRY
- 8-20 DAIRY
- 8-21 DAIRY
- 8-22 DAIRY
- 8-23 DAIRY
- dba_hist_active_sess_history中sample_time的采样时间
- 第一天
- <a>标签中的href如何调用js代码
- 机器学习实战-数据探索(变量变换、生成)
- 凡哥带你玩转OpenMV-OpenMV中文教程
- 10-8 DAIRY
- 19.Oracle杂记——Oracle诊断进程监控脚本
- (转)江南愤青丨丨监管办法之后,网贷一地鸡毛(2016年)
- CSDN初见
- spring-mvc入门(一)——springmvc框架
- 20.Oracle杂记——Oracle诊断会话监控脚本
- Python中的operator.itemgetter函数和sorted函数
- C/C++数据结构通过顺序栈实现括号()匹配算法
- windows下安装Python virtualenvwrapper-win