- 博客(213)
- 收藏
- 关注
原创 Ural1073-Square Country
给定一个数n,求这个数最少由几个完全平方数相加得到。 状态转移方程:dp[i] = ∑dp[i-j*j]+1.#include <cstdio>#include <algorithm>const int maxn = 60000 + 5;const int inf = maxn;int dp[maxn];int main(int argc, char const *argv[]) {
2016-12-05 16:37:39 487
原创 Ural1118-Nontrivial Numbers
很少切数论的题,因为它过于抽象,数学要求很高….唉说到底还是菜….题目大意 首先定义trivial number,是一个自然数的所有小于它本身的因子之和除以它本身所得到的那个数。然后给定某个区间,要求在这个区间内寻找出那个trivial number最小的数字。大致思路 先筛一遍区间内的素数,然后从大到小寻找最大的那一个素数,这个数一定是区间内trivial number最小的数。用时0.
2016-12-01 22:57:34 531
原创 Ural1272-Non-Yekaterinburg Subway
简单的并查集问题,先用tunnel连图后再检查bridge的连通,如果不连通就需要用一座桥连通两个岛。#include <cstdio>const int maxn = 10000 + 5;int par[maxn];int rk[maxn];void init(int n) { for (int i = 0; i < n; i++) { par[i] = i;
2016-11-30 14:35:58 380
原创 Ural1709-Penguin-Avia
用并查集先筛选掉以及连通的边,然后再将未连通边加上即可。#include <cstdio>#include <cstring>#include <vector>using namespace std;const int maxn = 100 + 5;char mat[maxn][maxn];char ans[maxn][maxn];struct edge { int u, v;};v
2016-11-30 13:54:29 404
原创 Ural1136-Parliament
题目大意 给出一棵二叉搜索树左子树+右子树+根的后序遍历,要求输出右子树+左子树+根的遍历顺序解题思路 根据给出的遍历顺序可知最后一个节点一定是根节点,然后通过该根节点寻找它的左子树(所有节点小于根节点)和它的右子树(所有节点大于根节点),然后递归地先搜索右子树,再搜索左子树,最后输出根节点即可代码#include <cstdio>const int maxn = 3000 + 5;in
2016-11-27 21:18:14 408
原创 Ural1471-Distance in the Tree
给定一棵树,求两个节点之间的距离。 以0为根节点,先dfs求出遍历的节点顺序和对应的节点深度,记录每个节点在欧拉序列中第一次出现的下标,以及每个节点到根节点的距离。 预处理RMQ能够快速得到在欧拉序列中的某个区间中离根最近的点(深度最浅),然后通过寻找两个节点u,v在欧拉序列中首次出现的位置区间内深度最浅的对应节点就是LCA(u,v),则u,v之间的距离为dis[u]-dis[t]+dis[v]
2016-11-27 17:08:02 475
原创 Ural1022-Genealogical Tree
拓扑排序#include <cstdio>#include <vector>#include <queue>using namespace std;const int maxn = 100 + 5;vector<int> G[maxn];int deg[maxn];int n;vector<int> ans;int main(int argc, char const *argv[]) {
2016-11-26 20:05:48 406
原创 Ural1982-Electrification Plan
有n个城市,其中k个城市有发电站,给出每个城市之间连接电线的花费,要求使每个城市通电的最小花费。 维护并查集用kruskal算法解决MST问题,标记每个发电站,在连边时取发电站为代表元素连边,连边时要判断两个城市的父节点是否是两个不同的发电站。#include <cstdio>#include <vector>#include <algorithm>using namespace std;co
2016-11-26 18:27:26 403
原创 Ural1353-Milliard Vasya's Function
给定一个数s,求从1到1e9的数中各位相加等于s的个数。#include <cstdio>// dp[i][j]表示长度为i,各位之和为j的个数int dp[15][90];int main(int argc, char const *argv[]) { for (int i = 1; i < 10; i++) { dp[1][i] = 1; } for (
2016-11-26 10:57:44 388
原创 Ural2062-Ambitious Experiment
给出n个数字,有两个操作,一个是查询某个位置上的数值,另一个是给定区间[l,r]和一个数字d,要求从l到r中的每个位置i开始,a[i]增加d,a[2*i],a[3*i], … ,每个位置都增加d。 方法是采用分桶法和平方分割,分成a个有floor(sqrt(n))个元素的桶,每个桶维护各自的信息,即增加了多少。 查询时,枚举因子求出这个数被增加了多少,再与原数相加即可。#include <cst
2016-11-23 00:14:04 515
原创 Ural1090-In the Army Now
有k行n列,求逆序对数最多的那一行的序号。#include <cstdio>#include <cstring>const int maxn = 10000 + 5;const int maxk = 20 + 5;int a[maxk][maxn];int fw[maxn];int n, k;inline int lowbit(int x) { return x & -x;}void
2016-11-22 16:37:19 357
原创 Ural1521-War Games 2
给定n和k求约瑟夫环中每次出圈的人的编号。 利用树状数组可以得到每个人的相对编号(在他之前有几个人)。 每次通过二分查找找到对应编号出圈的人,然后在他们的编号位置上-1.#include <cstdio>#include <vector>using namespace std;const int maxn = 100000+5;int fw[maxn];int n, k;inline int
2016-11-22 15:56:17 610
原创 Ural1470-UFOs
维护一个三维树状数组即可。 唯一的难点在于如何分解立方体从而得到从(x1, y1, z1)到(x2, y2, z2)的元素和。#include <cstdio>const int maxn = 128 + 5;long long bit[maxn][maxn][maxn];int n;int lowbit(int x) { return x & -x;}void add(int x, i
2016-11-21 21:12:25 392
原创 Ural1523-K-inversions
给定n个数字和一个k,求长度为k的下降子序列的个数。 dp[i][j]表示以a[i]为结尾,长度为j的下降子序列的个数。 因此: dp[i][j] = Sigma(dp[k][j-1]),其中k属于[1, i),且a[k] > a[i]. 维护一个树状数组以便于快速求出所有满足条件的dp[k][j-1]的总和。 先初始化dp数组,将dp[i][1]置为1,然后,更新dp[i][j],再在树
2016-11-21 11:39:55 452
原创 Ural1028-Stars
树状数组的简单运用。#include <cstdio>#include <algorithm>using namespace std;const int maxn = 15000 + 5;const int INF = 32000 + 5;typedef pair<int, int> P;P pos[maxn];int bit[INF];int level[maxn];int n;inline
2016-11-21 09:37:49 456
原创 Ural1987-Nested Segments
题目上说每两条线段要么没有公共点,要么完全覆盖,而且又规定了输入顺序,因此对于某个点来说后输入的长度一定短,所以用线段树做区间更新即可。 由于数字很大,需要先做一个离散化,把线段的点和询问的点离散后更新线段树。#include <cstdio>#include <map>using namespace std;#define lchild rt << 1, l, m#define rchild
2016-11-20 09:18:47 440
原创 Ural1671-Anansi's Cobweb
给定一个图中有n个点m条边,往图中不断删边并每次输出图被分成了几块。 使用并查集,相互连边的点放到同一个子集中去,这样一来就可以知道图被分成了几块。 但是并查集只能往里面加边却难以删掉一条特定的边,因此先用不会被删除的边建图,遍历并查集可得到删掉所有特定的边后图被分成的块数,然后往里添加最后被删的那条边,不断往前增加,知道添加到第二条被删的边为止。 在增加边时可以先判断边的两个端点u,v是否处
2016-11-19 11:10:59 475
原创 Ural1613-For Fans of Statistics
给定一串数字,一个区间和一个数x,问区间内是否有一个数正好等于x。#include <cstdio>#include <map>#include <vector>#include <algorithm>using namespace std;map<int, vector<int> > m;vector<int> ans;int main(int argc, char const *argv
2016-11-19 10:08:15 386
原创 Ural1306-Sequence Median
有n个数,求这n个数排序后的中间数,如果n为奇数,中间数即为排序后中间那个元素,如果n为偶数就是中间两个元素的平均数。由于内存只有1M,所以无法存下所有数值进行排序,因此,考虑将n/2+1个元素放入一个优先队列(堆)中,然后每次将剩下的元素逐个放进优先队列中并抛出堆中最大的元素。 这样以后如果n为奇数,队首元素即为中间数;如果是偶数,那么先记录队首元素,再抛出队首元素,原队首与当前队首元素之和除以
2016-11-18 20:35:13 340
原创 Ural1126-Magnetic Storms
给定一个区间长度n和一串数字,以-1结尾,输出每段长度为n的连续数中的最大值.#include <cstdio>#include <deque>#include <algorithm>using namespace std;typedef pair<int, int> P;int main(int argc, char const *argv[]) { int n; scanf(
2016-11-18 15:49:42 423
原创 Ural1106-Two Teams
二分图染色。#include <cstdio>#include <cstring>#include <cctype>#include <vector>using namespace std;const int maxn = 105;vector<int> G[maxn];vector<int> U;int mark[maxn];void dfs(int v) { if (mark[v
2016-11-17 20:28:30 401
原创 Ural2005-Taxi for Programmers
一开始没想到是深搜,以为是最短路,后来用脑洞大开想到了最小费用流… 其实只要dfs一下,如果当前点为终点的时候,判断是否所有点都已被访问过,再比较cost和ans,如果cost比ans小,记录下所有点的前驱点,再路径还原即可。#include <cstdio>#include <cstring>#include <vector>#include <algorithm>bool vis[6];
2016-11-17 09:45:27 335
原创 Ural1654-Cipher Message
题意全靠蒙… 维护一个栈,提取message的每个字符,如果栈顶元素与字符不同就将字符压入栈中,否则将栈顶字符弹出.#include <cstdio>#include <vector>#include <stack>#include <cstring>using namespace std;const int maxn = 200000 + 10;char mesg[maxn];int ma
2016-11-16 18:48:17 273
原创 Ural1837-Isenbaev's Number
有一个巨巨叫Isenbaev,现在给出n个队伍,如果是某人是他的队友,则这个人对应的数值为1,如果是他队友的队友则为2,以此类推。 首先在这n个队伍中,最多会有3*n个人,用map存在这些人的信息,编号并提取出总人数。 按照队伍里的人相互连边建图,bfs即可。 注意Isenbaev不在的情况,这是所有人都是undefined.#include <cstdio>#include <string
2016-11-16 17:59:51 332
原创 Ural1014-Product of Digits
给定一个数n,要求一个最小的Q,使得Q的每一位数相乘的积为n。 不断从9到2枚举n的因子,然后除掉,这样能够使得Q的位数最小。 最后倒序输出即可。#include <cstdio>#include <vector>std::vector<int> v;int main(int argc, char const *argv[]) { int n; while (scanf("%d
2016-11-15 21:44:13 344
原创 Ural1082-Gaby Ivanushka
题目给了一段代码,问你要n个数字,使得这n个数字输入到这段代码中能够输出”Beutiful Vasilisa”。 仔细阅读发现这段代码给出的算法即是快排,并且要求长度为n的序列在经过快排后,算法中i,j的移动次数为(N * N + 3 * N - 4) / 2才算满足条件。先说答案:任意n个数满足从小到大排列即可输出”Beutiful Vasilisa”。当n个从小到大的数输入程序时,首先运行Q(
2016-11-15 21:02:40 329
原创 Ural1044-Lucky Tickets. Easy!
给定一个n,表示n位编号,求n位编号中前半部分和后半部分之后相等的编号个数。 网上的题解大都只写出最后答案而不指出过程,而我用的是暴搜预处理,按位从0到9赋值,搜索出个数。#include <cstdio>#include <cmath>int a[10];int c[10];void dfs(int x, int n) { if (x == n + 1) { int
2016-11-15 17:51:13 384
原创 Ural1079-Maximum
递归预处理#include <cstdio>#include <algorithm>using namespace std;const int maxn = 100000 + 5;int a[maxn];int f(int x) { if (x == 0 || (x != 0 && a[x])) { return a[x]; } if (x % 2 == 0
2016-11-15 15:22:05 285
原创 Ural1005-Stone Pile
给出n个数,要求将其分成两堆,求两堆数字总和的差值最小。 一开始傻傻的用next_permutation,第二个数据就TLE了…. 其实搜索每个元素,先放在一堆搜索,再回溯放在另一堆搜索,复杂度为2^20.#include <cstdio>#include <cmath>#include <cstdlib>const int INF = 20 * 100000;int a[25];bool
2016-11-15 14:02:54 416
原创 Ural1876-Centipede's Morning
一只蜈蚣有40只左脚和40只右脚,在它的床下有a个左拖鞋和b个右拖鞋,它会先用左脚寻找拖鞋并穿上,每次花费一分钟。如果是左拖鞋就穿在左脚上,如果是右拖鞋就将拖鞋脱下并穿到右脚上,多花费一分钟。当左脚都穿上了拖鞋后,用右脚寻找拖鞋并穿上,同样花费一分钟,如果是左拖鞋就脱下并扔到一边,多花费一分钟。 给定a,b求最坏情况。 第一种情况:用左脚寻找到的拖鞋都是右拖鞋,寻找完所有右拖鞋后再穿上左拖鞋,花
2016-11-14 23:03:37 309
原创 Uva514-Rails
有n辆火车入栈出栈,判断出栈顺序是否合法 用a,b两个变量标记,将a入栈直到找到第一个t[a] == b的数,然后判断栈内的数与t[b]是否匹配。#include <cstdio>#include <stack>using namespace std;int t[1005];int main(int argc, char const *argv[]) { int n; while
2016-11-13 19:19:14 424
原创 POJ2886-Who Gets the Most Candies?
先打表求反素数,这些反素数表示能够得到最多的糖果的回合数。 因此只要找出n以内最大的反素数,就表示在那个回合出局的人拿到最多的糖果,糖果数为该反素数的因子个数。 用线段树维护圈内的剩余人数和原来的位置,用类似约瑟夫环的方式求出每个人的相对位置,更新线段树,找出在那一个回合出局的人。 tree[1]表示剩下的人数。 当某个人手中的数字为负时,有可能会极小,因此要注意使余数为正。#include
2016-11-10 20:01:07 260
原创 POJ2777-Count Color
线段树真是一种优雅的解决方案。 将30种颜色用二进制编码,然后用线段树每个节点维护颜色的种类。void push_up(int rt) { tree[rt] = tree[rt<<1] | tree[rt<<1|1];}巧妙的位运算使得通过每个二进制位即可知道在这个区域内一共有多少种颜色。另外用lazy数组延迟标记以优化算法速度。需要注意的是输入的a,b需要比较一下,因为可能会存在a >
2016-11-08 20:50:17 293
原创 POJ2828-Buy Tickets
用线段树维护队伍内剩余的空位和位置里人的val值,然后从后往前给每个人安排空位,如果有人就往后移动。 神奇的是这道题允许最后输出存在空格哟!#include <cstdio>#define lchild rt << 1, l, m#define rchild rt << 1 | 1, m + 1, rconst int maxn = 200000 + 5;const int sz = 1 <<
2016-11-07 21:46:43 320
原创 POJ3629-Kindergarten
一个幼儿园里女生相互认识,男生也相互认识,另外有些男生女生相互认识,老师要带一群相互认识的孩子,问最大数量。 由于女生相互认识,男生相互认识,因此这个图的补图一定为二分图,于是就把这个图转换而求补图的最大独立集。 补图中不认识就代表了在原图中相互认识。#include <cstdio>#include <cstring>#include <vector>const int maxn = 20
2016-11-01 21:12:14 535
原创 POJ1466-Girls and Boys
好纯洁的题目呀! 求最大独立集,用顶点数减去二分图最大匹配即可。#include <cstdio>#include <cctype>#include <vector>const int maxv = 1000 + 5;char s[maxv];int n;std::vector<int> G[maxv];int match[maxv];bool used[maxv];void add_e
2016-11-01 20:06:47 331
原创 POJ2112-Optimal Milking
二分最大流答案,注意上界是INF而不是200.#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>using namespace std;const int maxk = 30 + 5;const int maxc = 200 + 5;const int maxv =
2016-10-31 22:33:22 325
原创 POJ1274-The Perfect Stall
裸的二分图匹配问题。 两种做法,第一种是建图转换成最大流流的问题求解,另一种直接用二分图匹配模板。 最大流:#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>using namespace std;const int maxn = 400 + 5;const l
2016-10-30 21:38:01 238
原创 POJ2987-Firing
利用Dinic求最小割,求最大权闭合图。 其中最大权=正权和-最小割,即最大裁员收益。 在求出最小割之后,遍历搜索残余网络的顶点个数即可求出裁员的个数。数据太大需要用long long。 计算残余网络的顶点个数时要去掉源点。#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algo
2016-10-30 20:23:02 313
原创 HDU5916-Harmonic Value Description
给定一个n和k,要求组合1-n之间的数使它们gcd为第k小。 组合时相邻两数的gcd一定为1,因此要使得组合第k小,就可以将k与2k相邻,其余的各项相邻的数之间gcd为1. 可以这样排序: 2, 3, 4, … ,k, 2k, 2k+1, 2k+2, …, n, 1, k+1, k+2, … ,2k-1 其中区间[2, k],[2k+1, n],[1, 2k-1]都连续,因此区间内相邻gcd
2016-10-28 19:36:24 539
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人