题解
文章平均质量分 73
wwwiskey
学生
展开
-
POJ 1785 Binary Search Heap Construction 【笛卡尔树构造,线段树RMQ(Range Max/Min Query)】
题目注意: 两个要求,1. 第一关键字满足搜索序,2. 第二关键字满足堆的性质。这道题目的标准(简单)解法:笛卡尔树。但是还有: 分治+RMQ, 其中,RMQ问题有两种方法:线段树和Sparse Table算法。笛卡尔树定义:笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为key,一个为value。光看key的话,笛卡尔树是一棵二叉搜索树,每个节点的左子树的key都比原创 2013-01-24 20:24:40 · 3772 阅读 · 6 评论 -
CF 256C Furlo and Rublo and Game【博弈论,SG函数】
暴力的求SG函数会超时,正解是先处理出10^6以内的SG值,对于更大的,开根号之后计算出。小数据观察可以发现sg函数值成段出现,而且增长速度很快,因此可以计算出来每一段的范围,只需打表即可。#include #include using namespace std;typedef long long ll;ll x, a[] = {3, 15, 81, 6723, 5062原创 2013-08-05 15:39:40 · 1467 阅读 · 0 评论 -
POJ 2960 S-Nim 【博弈论,SG函数】
经典的Nim游戏题目中已经给出了——每一堆选取的数量没有限制。S-Nim游戏仅仅是限制了每一次从每一堆中选取的个数,依旧用sg函数计算即可。经典的Nim游戏中sg(x) = x,所以结果就是每一堆的状态直接xor即可,S-Nim游戏先计算每一堆的sg函数值,然后判断方法依旧是用xor。#include #include #include using namespace s原创 2013-08-05 16:48:07 · 2480 阅读 · 0 评论 -
HDU 2222 Keywords Search 【AC自动机模板】
询问有多少个模式串出现在了文本串里面。将模式串插入Trie树中,然后跑一边AC自动机统计一下就哦了。献上一份模板。#include #include #include #define MAX_NODE 240005#define MAX_CHILD 26using namespace std;class AC_Automaton {public: int c原创 2013-08-06 10:30:49 · 2849 阅读 · 1 评论 -
CF 294E Shaass the Great【Tree】
将树的一条边移掉,然后将这条边重新连接两棵子树,使新树:两两点对的距离之和最小。枚举删掉的边,对每种情况都计算一下,然后取最小值。对于每种情况,假设左子树的两两点对和为S1,右子树为S2,子树结点个数分别为C1,C2,两个子树到树根的距离和分别为R1,R2,当前枚举的边的权值为w,则整棵树的代价为:两棵子树的点对和+经过当前边的点对和S1 + S2 + (C1 + C2)*w +原创 2013-08-19 22:19:59 · 1260 阅读 · 0 评论 -
HDU 2896 病毒侵袭 【AC自动机】
HDU 2222 仅仅求出了和文本串匹配的模式串个数,本题要求求出匹配的模式串的编号。不同的部分在代码中的注释部分。#include #include #include #include #include #define MAX_NODE 60005#define MAX_CHILD 130using namespace std;vector ans;class原创 2013-08-06 11:55:12 · 1259 阅读 · 0 评论 -
HDU 3065 病毒侵袭持续中
询问每个模式串在文本传中出现的次数。文本串中出现的字符不一定都是大写字母,只需要在匹配的时候,对文本串进行特殊处理,将连续的大写字母段当成合法的一个文本串即可。然后……就是简单的统计了。#include #include #include #include #include #include using namespace std;int原创 2013-08-07 16:42:50 · 928 阅读 · 0 评论 -
ZOJ 3430 Detect the Virus 【AC自动机+解码】
解码的那些事儿,不多说。注意解码后的结果各种情况都有,用整数数组存储,char数组会超char类型的范围(这个事最蛋疼的啊)建立自动机的时候不能用0来判断结束。#include #include #include #include #include #include using namespace std;vector ans;struct AC_Automata原创 2013-08-08 09:57:20 · 1374 阅读 · 0 评论 -
TC SRM 570 div2 1000【Tree,树上统计】
将一棵树上的所有结点分成两个集合(其中一个集合可以为空),但是“人类”的集合必须是联通的。问总共有多少种分法。将整棵树确定一个根,那么每个结点被选择之后,其父节点不被选择(此节点是个分界)的方案数=(所有儿子的方案数+1)的乘积。(+1表示当前子树的所有儿子都不选择)最后将所有结点作为分界的结果累加起来即可,然后+1(所有结点都不被选择)const int N = 55;c原创 2013-08-20 20:29:33 · 1167 阅读 · 0 评论 -
POJ 3233 Matrix Power Series 【矩阵快速幂,矩阵加速】
| A+A^2+A^3+…Ak | |A A| (k-1)次方 | A || | = | | | || E | |0 E| | E |A是输入的矩阵#include #include #include #include原创 2013-08-21 11:11:40 · 1100 阅读 · 0 评论 -
CF 256E Lucky Arrarys 【线段树+DP】
规定Lucky Array中任意相邻的两个数(ai, ai + 1)在w数组中为1。数组初始为0,问有多少种排列方式使数组是Lucky的。并且每次更新之后都要给出总的方案数。动态规划可以求相邻两个区间合并之后的结果f(i, j)表示当前区间以i开头,以j结尾的总方案数。那么配合更新操作,我们就可以用线段树来维护。树中每个节点上面都有一个f数组记录当前区间的方案数。对于每次更新后的询原创 2013-08-05 10:07:43 · 1091 阅读 · 0 评论 -
HDU 1729 Stone Game 【博弈论,SG函数】
n个瓶子,每个瓶子里面有一些石头,每次向瓶子里面放石头的数量不能超过瓶子中已经存在的石头数量的平方。很容易看出是“组合游戏和”,因此只需要求出每个瓶子的sg函数值,然后求Nim和即可。寻找必败态:设t,t*t +t = s,因此1. c > t 则当前状态是必胜态,因为c*c+c >= s成立2. c == t 则当前状态为必败态,因为最多放c*c个石头,瓶子未满,对手原创 2013-08-05 19:37:10 · 2714 阅读 · 0 评论 -
POJ 2201 Cartesian Tree 【笛卡尔树】
构造笛卡尔树。我用的是 排序+左旋 的方式,这种方式并不是最好的构造方式,先写出来再说,今天不行了,改天在学习其他的算法。构树技巧:增加一个虚拟的根节点,根节点的value优先级最高,可以保证此节点一直是根节点。这道题目的数据有点……,所以不需要判断不合法的,所有的数据都可以构成笛卡尔树,所以判断NO的就可以省了。。。。⊙﹏⊙b汗排序+左旋:#inc原创 2013-01-25 00:41:58 · 1367 阅读 · 0 评论 -
CF 19D Points 【线段树+平衡树】
在平面上进行三种操作:1、add x y:在平面上添加一个点(x,y)2、remove x y:将平面上的点(x,y)删除3、find x y:在平面上寻找一个点,使这个点的横坐标大于x,纵坐标大于y,而且要求他的横坐标尽量小,如果有多个点满足,则选取横坐标尽量小的前提下,纵坐标最小的点。方法:将横坐标x离散化,每一个坐标x对应的y用一颗平衡树维护(C++中的set),原创 2013-07-31 16:54:41 · 1142 阅读 · 0 评论 -
CF 8D Two Friends 【二分+三分】
三个地点构成一个三角形。判断一下两个人能否一起到shop然后回家,如果不能:两个人一定在三角形内部某一点分开,假设沿着直线走,可以将问题简化。三分从电影院出来时候的角度,在对应的直线上二分出一个分离点即可。三分角度的方法:在shop和home两个点之间找一个点p,链接p和电影院,在这个线段上面二分出分离点。注意:精度。#include #inclu原创 2013-07-26 11:19:20 · 1072 阅读 · 0 评论 -
CF 161D Distance in Tree【树DP】
题目大意:给一棵树,求树上两点之间距离为K的点对数目。方程含义:dp(i,j)表示从已经遍历过的点到当前点i,路径长度为 j 的路径条数。因此,对于当前点,每当遍历了其中一个儿子节点的时候,首先统计当前情况下的结果,然后要更新dp(i, j)初始条件dp(i,0)= 1#include #include #include using namespace std;#d原创 2013-07-26 17:08:37 · 1914 阅读 · 0 评论 -
CF 121E Lucky Array 【树状数组】
这个题目的数据感觉不能更水了。从复杂度上计算,肯定有极限数据可以卡掉暴力方法的么。总之,暴力的做法就是树状数组了,对于区间更新,就挨个更新就是了。当然,判断是否是Lucky Number的话,可以用一个数组标记一下,因为题目中有说数据不会超过10000的。总之就是一个非常不靠谱的方法过了……话说用线段树的区间操作以及延迟标记的话,真心不知道怎么判断加上d之后的Lucky Number的个数,o原创 2013-08-02 19:47:22 · 1320 阅读 · 0 评论 -
CF 319B Psychos in a Line 【单调队列】
维护一个单调下降的队列。对于每一个人,只需要找到在他前面且离他最近的可以杀掉他的人即可。#include #include #include #include using namespace std;#define N 100005vector v;int f[N], n, t, cnt;int main() { scanf("%d", &n);原创 2013-08-03 11:42:39 · 1537 阅读 · 0 评论 -
CF 242E XOR on Segment 【线段树】
两种操作:1、求区间和2、对区间上的每一个数进行异或(xor)运算直接维护区间和的话区间更新无法进行,所以,要维护的信息是区间内按位和(即每个二进制位出现的次数),那么进行xor运算的时候,只需要进行0 和 1的转换就可以了。这样的话,就是一个基本线段树+延迟操作+维护各个二进制位信息。#include #include using namespace st原创 2013-08-03 10:04:35 · 1670 阅读 · 0 评论 -
HDU 4638 Group 【树状数组,分块乱搞(莫队算法?)】
根据题目意思,很容易得出,一个区间里面连续的段数即为最少的group数。题解上面给的是用树状数组维护的。询问一个区间的时候,可以一个一个的向里面添加,只需要判断a[i]-1 和 a[i]+1是否已经添加在内,如果两个都在,则总段数减1,如果两个都不在,总段数加1,其他情况总段数不变了。这里有一个需要深入理解的就是其实无论是按顺序添加还是随便添加,统计结果是不变的,但是要看怎么维护了。每原创 2013-08-03 19:39:29 · 2919 阅读 · 0 评论 -
HDU 1864 Brave Game 【组合游戏,SG函数】
简单取石子游戏,SG函数的简单应用。有时间将Nim和、SG函数总结一下……暂且搁置。#include #include #define N 1002int n, T, m, sg[N];bool vis[N];int main() { scanf("%d", &T); while (T--) { scanf("%d%d", &n原创 2013-08-05 15:34:32 · 879 阅读 · 0 评论 -
HDU 4664 Triangulation【博弈论】
一个平面上有n个点(一个凸多边形的顶点),每次可以连接一个平面上的两个点(不能和已经连接的边相交),如果平面上已经出现了一个三角形,则不能在这个平面上继续连接边了。现在总共有N个平面,每个平面上都有若干点。(就是有N个相同的游戏同时进行了)。想法很单纯,就是计算出每一个平面上游戏的sg函数值,然后求Nim和就哦了。sg函数暴力求法:一个平面上连接点时,不能连接已经有边的顶点原创 2013-08-09 21:08:16 · 1837 阅读 · 1 评论 -
HDU 4661 Message Passing 【Tree】
题意:给一棵树,每一个结点都有一个信息,每一个时刻,某一对相邻的结点之间可以传递信息,那么存在一个最少的时间,使得所有的节点都可以拥有所有的信息。但是,题目不是求最短时间,而是求最短时间的情况下,有多少种传递方式:某一时刻传递信息的双方不一样则认为是不同的传递方式。(表述的不是很清楚,自己看原题了)容易的出,最短的时间内,当然是每个节点将自己的信息想外传出去一次,并且接受一次信息,原创 2013-08-09 19:45:15 · 1847 阅读 · 0 评论 -
HDU 4679 Terrorist’s destroy【Tree】
给一棵树,每条边上都有一个权值,去掉树上任意一条边之后,分成两个子树,两个子树的最长路与这条边上的权值相乘,的到一个乘积。问去掉那一条边可以使这个乘积最小。首先找到树上的最长路,那么删边的时候有两种情况:1. 这条边是最长路上的边2. 这条边不是最长路上的边对于第一种情况,很容易计算出乘积。对于第二种情况,只需要计算出被分成的两个子树里面的最长路径长度即可,这个可以预处理一下。原创 2013-08-15 19:23:47 · 2131 阅读 · 2 评论 -
BZOJ 2599 [IOI2011]Race【Tree,点分治】
给出N(1 点分治,这道题目和POJ 2114很接近,2114是求是否存在长度为K的边,但是那个K比较大。但是这道题目的K比之小了10倍。1. 用V[i]表示到当前树根root的路径长度为i 时的点(赋值为root结点即可),这样就可以用来判断两条到根的路径长度之和是否等于K: 结点a的root的距离为i,结点b到root的距离为j,处理完a之后会得到V[i] = root,那么原创 2013-08-16 17:09:29 · 3674 阅读 · 0 评论 -
POJ 2114 Boatherds【Tree,点分治】
求一棵树上是否存在路径长度为K的点对。POJ 1714求得是路径权值刚开始我以为只要在分治过程中出现过长度为K的就算是找到了,其实不然,因为可能是相同子树里面的两个结点,这个结果显然是错误的。#include #include #include #include using namespace std;struct node { int v, l; node(原创 2013-08-16 14:53:17 · 4132 阅读 · 1 评论 -
HDU 4712 Hamming Distance [预处理+暴力]
惨不忍睹,不能多说了。直接看代码吧。。。就是暴力了。。。#include #include #include #include #include using namespace std;#define N 100020int a[N<<1], n;vector c[22];int f[1<<21];int main() {#ifndef ONLINE_JUDG原创 2013-09-09 11:23:17 · 2599 阅读 · 0 评论 -
HDU Ads Proposal 【树状数组】
题意:N个customer,M个advertisement,每个ad只属于一个cus,每个ad都有一个点击量和一个长度值。现在对于每个询问,求出所有cus的前k大点击量的广告的总长度。对于每个ad,求出他在所属的cus里面的排名,这个一边排序就可以了。将长度累加到对应排名上面。树状数组维护查询就可以了。#include #include #include us原创 2013-10-04 19:51:39 · 1383 阅读 · 0 评论 -
HDU 4000 Fruit Ninja 【树状数组】
题意:给1-N的一个排列,找出所有的(x, y, z) 使得x 题解:对于每个x,只需要找到比x靠后,而且比x大的数的个数,这样的组合数为:n*(n-1)/2这里面有重复的情况:i 树状数组统计x之前出现的比x小的个数,剩下的就全部可以算出来了。#include #include #include #include using namespace std原创 2013-10-04 18:15:14 · 1307 阅读 · 0 评论 -
HDU 4474 Yet Another Multiple Problem【BFS+一个判断技巧】
题意:0-9这十个数字里面的若干个数字组合出一个数,使这个数是N的倍数,求最小的这个这样的数,不存在的话输出-1。按照数的位数BFS,从小向大枚举就可以保证构造出来的数是递增的,如果不加判断就直接搜索的话,复杂度非常高。因此需要剪枝。优化方法:如果一个数%N==0,那么这个数就是N的倍数。在没有找到的前提下,如果A%N==B%N,而且A因此我们只需要维护组合出来的数%N的值即可,如果在原创 2013-10-06 20:14:10 · 3488 阅读 · 0 评论 -
HDU 4288 Coder 【线段树+离线处理+离散化】
题意略。离线处理,离散化。然后就是简单的线段树了。需要根据mod 5的值来维护。具体看代码了。/* 线段树+离散化+离线处理*/#include #include #include #include using namespace std;typedef long long ll;#define N 100010ll sum[N<<2][5];int a[原创 2013-10-06 13:36:19 · 1785 阅读 · 0 评论 -
HDU 4294 Multiple【BFS】
结论:任意一个N的的倍数,都可以由最多两个数组组合而成。证明:AAAA...A % N的值是有限的,那么一定存在个数不同的AA..A组合%N之后的值和它相同。那么这两个组合相减就是N的倍数了。以上证明只能说明最多需要两个,并不能说明由两个数组成的N的倍数一定是AAAA..A0000的形式,理解一下就可以了。那么这个题目就可以先判断由一个数组合,然后判断两个数的组合即可。方法是B原创 2013-10-06 20:02:17 · 1386 阅读 · 0 评论 -
HDU 4676 Sum Of Gcd【数论,数据结构(分块)】
静态区间查询,没有更新操作,瞬间就想起来了哪个O(n*sqrt(n))的做法。关键是区间转移的时候不会处理了,只能说数学拙计了……对于此类问题的时间复杂度分析,详见:http://blog.csdn.net/yang_7_46/article/details/9618637买一送一,以一场多校的题目是题解给的是树状数组,其实也可以用这个算法水过,时间也挺快。http://blog.cs原创 2013-08-15 21:10:56 · 3011 阅读 · 1 评论 -
POJ 1987 Distance Statistics【Tree,点分治】
这道题目和POJ 1741基本一样了。树上的分治。此类算法参考论文:09年国家集训队论文《分治算法在树的路径问题中的应用——漆子超》#include #include #include #include using namespace std;#define N 40005struct node { int v, l; node() {};原创 2013-08-14 20:22:52 · 1966 阅读 · 0 评论 -
POJ 2778 DNA Sequence【AC自动机+矩阵快速幂】
#include #include #include #include #include #include using namespace std;typedef long long ll;struct AC_Automata { #define Nn 102 #define M 4 int ch[Nn][M], val[Nn], f[Nn], last[原创 2013-08-10 21:36:32 · 2991 阅读 · 2 评论 -
HDU 2825 Wireless Password【AC自动机+DP】
给m个单词,由这m个单词组成的一个新单词(两个单词可以重叠包含)长度为n,且新单词中包含的基本单词数目不少于k个。问这样的新单词共有多少个?m很小,用二进制表示新单词中包含基本单词的情况。用m个单词建立AC自动机,可以求出所有单词之间相互包含的情况,AC自动机的后缀特性(每个结点的失配边指向新结点,新节点到trie树根的字符串是当前节点字符串的后缀)。动态规划:f(原创 2013-08-12 14:03:46 · 1158 阅读 · 1 评论 -
POJ 1625 Censored【AC自动机+DP+大数】
给n个字母,构成长度为m的串,总共有n^m种。给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数。将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后缀的字符串是否包含非法字符串(p个字符串中的任何一个)。状态转移方程:f(i, j) += f(i-1, k) f(i, j)表示长度为i的字符串,结尾为字符j,方程j和k的关系可以从自动机中原创 2013-08-11 16:05:08 · 2438 阅读 · 1 评论 -
POJ 2926 Requirements【最远曼哈顿距离】
n个5维坐标的点,求这n个点中曼哈顿距离的最大值。暴力枚举肯定超时。只考虑二维空间上两个坐标之间的曼哈顿距离(x1, y1) 和 (x2, y2),|x1-x2| +|y1-y2|去掉绝对值符号后共有下列四种情况(x1-x2) + (y1-y2), (x1-x2) + (y2-y1), (x2-x1) + (y1-y2), (x2-x1) + (y2-y1)转化一下:(x1+y原创 2013-08-13 20:54:06 · 5456 阅读 · 4 评论 -
CF 258E Little Elephant and Tree 【线段树,树上DFS序列】
题意:对一颗树进行m次操作,每次操作(a,b)都是在节点a和b的子树的所有节点后边加入操作的序号。最后询问每个节点分别与多少个其他节点拥有相同的操作编号。英文题解:http://codeforces.com/blog/entry/6213首先根据DFS顺序将树转化为一个线段树,剩下的问题就可以用线段树来解决了。如果节点x进行了第i种操作,那么x所有的儿子节点也都进行了相同的操作,只需要原创 2013-07-30 02:18:25 · 1952 阅读 · 0 评论 -
HDU 4666 Hyperspace【最远曼哈顿距离+优先队列】
这个题是动态的求最远曼哈顿距离。做法和POJ 2926 Requirements一样,都是通过二进制枚举符号的情况。每插入一个节点都要询问最大值和最小值,因此用一个优先队列或者堆维护就可以了。#include #include #include #include #include using namespace std;#define N 60010#define i原创 2013-08-14 08:56:40 · 1880 阅读 · 0 评论