摘要:题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1939来自:刘汝佳大白书P201.解题思路:构造一棵线段树,其中每个结点维护三个值,记录最大前缀和,最大后缀和最大连续和。最大连续和要么完全在左段,要么完全在右段,要么在跨越中线。就是会是左段的最大后缀和+右段的最大前缀和。。。。代码也是刘汝佳写的哦代码: 1 // LA3938 Ray, Pass me the dishes! 2 // Rujia Li
阅读全文
摘要:题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2176RMQ,就是范围最小值的缩写,这个算法是Tarjan 的 Sparse-Table 算法,复杂度为O(n*log(n)).就是用数组d[i][j]表示范围[i,i+2^j-1]中的最小值。然后有递推式d[i][j] = min(d[i][j-1],d[i+2^(j-1)][j-1]).有边界条件d[i][0] = A[i].然后就能求出所有的d[i][j].查询时只
阅读全文
摘要:题目链接:刘汝佳,大白书,P197.枚举裁判的位置,当裁判为i时,可以有多少种选法,如果已经知道在位置i之前有ci个数比ai小,那么在位置i之前就有i-1-ci个数比ai大。在位置i之后有di个数比ai小,那么在位置i之后就有n-i-di个数比ai大。这样,选法数有ci*(n-i-di)+di*(i-1-ci).注意到ai的值各不相同且ai的值最大不超过10^5,那样就可以用v[a[i]]表示a[i]是否已经存在,这样当顺时针扫描的时候,每次更新v[a[i]] = 1;//表示已经存在。比ai小的数的个数就是sum(v[j]) j 2 #include 3 #include 4 using n
阅读全文
摘要:题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1028比较简单,用数组d[i]表示结点i和祖先结点的距离,查询时压缩路径并更新d[]数组。刘汝佳大白书(P193):贴代码: 1 #include 2 #include 3 const int N = 20004; 4 int pa[N],d[N]; 5 int findset(int x) 6 { 7 if(pa[x] == -1) return x;
阅读全文
摘要:题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3148题意:给K个数组,每个数组含有K个整数,从每个数组中各选一个数加起来,得到一个sum,这样的选法一共有K^k种,现在求这样的和中最小的K个sum.解法:先考虑两个数组的情形假设A1,第一个数为和,第二个数为B的序号,放入优先队列,然后从优先队列中弹出最小的,这个最小值一定是所有和中最小的,同时压入A[a] + B[b+1],A[a]+B[b+1] = s-B[b]+
阅读全文
摘要:直接贴代码吧 1 #include 2 #include 3 char P[10004],T[1000006]; 4 int f[10004]; 5 int n,m; 6 void getfail() 7 { 8 f[0] = 0; 9 f[1] =0;10 for(int i=1; i<m; ++i)11 {12 int j=f[i];13 while(j && P[i] != P[j]) j = f[j];14 f[i+1] = P[i]==P[j] ? j+1:0;15 }16 }17 int KMP...
阅读全文
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4638解题思路:题意为询问一段区间里的数能组成多少段连续的数。先考虑从左往右一个数一个数添加,考虑当前添加了i - 1个数的答案是x,那么添加完i个数后的答案是多少?可以看出,是根据a[i]-1和a[i]+1是否已经添加而定的,如果a[i]-1或者a[i]+1已经添加一个,则段数不变,如果都没添加则段数加1,如果都添加了则段数减1。设v[i]为加入第i个数后的改变量,那么加到第x数时的段数就是sum{v[i]} (1 2 #include 3 #include 4 #include 5 using
阅读全文
摘要:这题做完后觉得很水,主要的想法就是逆过程思考,原题是截断,可以想成是拼装,一共有n根木棍,最后要拼成一根完整的,每两根小的拼成一根大的,拼成后的木棍长度就是费用,要求费用最少。显然的是一共会拼接n-1次,如果把每根木棍最初的长度想成叶子节点,两个节点的父节点就是这两个节点的长度相加。那么求的就是这n-1个父节点的总和最少。为实现这个目标,我们使每个父节点的值尽可能的少,由此想到哈夫曼编码的原理。初始条件为一共n根木棍。然后从中选出最短的两根,将这两根拼接成一根,这样得到的父节点的值是最小的。然后将这根木棍放进原来的木棍中,重复该步骤(从木棍堆中选出最短的两根,拼接成一根,放回木棍堆中),进行了
阅读全文
摘要:题目网址:http://122.207.68.93/OnlineJudge/problem.php?id=1294题意是给你一个字符串,字符串中只包含O和R,要你求满足条件的最长的连续子序列的长度,输出该长度。。条件是,连续子序列中O的个数是R的个数的K倍(K已知)想法如下:设这个满足条件的子序列O的个数为x,R的个数为y则有x = k*y即有x + (-k)*y = 0那么如果令R的权值为-k,O的权值为1,这段序列的和即为0令sum[i]为前i项之和。。。如果有sum[i] == sum[j],证明a(i+1) + a(i+2) + ```` + a(j)的和为0,也就是说出现可行解,其长
阅读全文
摘要:这个题显然是用并查集,主要是涉及到并查集中结点的删除,一般而言构造的并查集要独立出结点,直观的想法是直接修改它的父结点为自己,但这样会出现错误。它原来的子结点也跟着一起独立出来了,这和题目是不符合的(题目只要求独立出要独立的那个,它的孩子结点还是应该在本来的那棵树上),考察合并函数发现,合并时总是把一个集合的根结点作为另一个集合的根结点。之所以不好把某个结点直接独立出来是因为它本身还是别的点的父结点,而这种情况出现的原因就是自己做过根结点。为保证编号为0-n-1的结点永远只做叶子结点,只需要给它们找个虚拟的根结点即可,也就是说,当某个结点只含自己时的初试状态不是p[x] = x,而是p[x]
阅读全文
摘要:这个题算是考察一下大家的逻辑思维,很可惜,我的还不行,这题我搜了别人的解题报告,没看几行字就不想看了,但今天又很想A了这题,又一次去搜了解题报告,看到了CSDN的博客上有一篇名为史上POJ 1182 最详细的解题报告,写得不错,我终于耐心看了下去,看完后,发现这个题和那个称重的并查集的题的思路基本上是一样一样的啊。下面详细讲一下:先定义每个动物的两种属性,一个是父结点是谁,一个是和父结点的关系,定义如下:struct Animal{int parent; //父结点的编号int relation;//和父结点的关系,0-和父结点是同类 1-被父结点吃 2-吃父结点} a[MAXN];下面推两个
阅读全文
摘要:https://icpcarchive.ecs.baylor.edu因为给你的是两物品的重量差,问你的也是两物品的重量差,所以,如果告诉你两物品的重量差,这就相当于给你一种等价关系,把两物品所在的集合合并,并能推导出合并完的集合内所有的物品的差,为了加速该过程,可以在每个子结点记录自己与父结点的重量差,然后在查找时路径压缩,让结点的父结点直接是根结点,重量差就要更新,这步要做对,自己推导推导怎么做,然后在合并两集合时采用启发式合并,说白了就是把结点数少的那个集合作为结点数多的集合的子结点。这样操作会少一些。贴代码:View Code 1 #include 2 #define MAXN ...
阅读全文