随笔分类 - UVA
摘要:26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大。本来想学习一下cdq分治的,看到论文上的凸包、斜率就暂时放一边了,只知道和一般的分治的不同是左子问题可以用来解决右边的子问题。今天下午YY了一个离线的分治做法,也不知道叫不叫...
阅读全文
摘要:每次操作是独立的,而且顺序并不影响,作用在同一个结点上的d可以叠加,所以令x(u) = sigma(dui).最后就是要确定所有的x(u)。因为m越大,满足条件的边就越少,二分答案m。对于一条边a->b,可以列出一个不等式d(a,b) +x(a)-x(b)>=m,移项可得x(b)-x(a)0,意味着...
阅读全文
摘要:二分,判断的时候,一个点一个点的考虑肯定是不行啦,考虑的单位是一个区间,每次左端点尽量向左边移动,右端点尽量向右,得到下次可以达到的范围,检查一下和下一个区间有没有交集。#includeusing namespace std;const int maxn = 1e5+5, maxns = 1e6+5...
阅读全文
摘要:很容易想到二分,问题在与判断一个解的可行性。贪心,时间点最多两万,可以模拟每个时间点,将事件按开始时间排序,每次优先选已经开始了的且结束时间最早的任务来做,如果某个任务在deadline之前还没有结束说明当前解不可行。R的上界不太好估计,(远远达不到总和,但是比maxw大,因为任务在时间上有重叠),...
阅读全文
摘要:贪心,假如任意给出一个序列,如果两两交换了以后会变大,那么就交换,直到不能交换为止。#includeusing namespace std;const int maxn = 51;string s[maxn];int rk[maxn];bool cmp(int x,int y){ int i ...
阅读全文
摘要:问题可以转化为草坪的边界被完全覆盖。这样一个圆形就换成一条线段。贪心,从中选尽量少的线段把区间覆盖,按照把线段按左端点排序,记录一个当前已经覆盖区间的位置cur,从左端点小于等于cur选一个右端点最大的作为这次选的区间,如果没有符合条件的,说明不可能完全覆盖。r*r会爆int...#includeu...
阅读全文
摘要:UVA 11636 Hello World二的幂答案就是二进制长度减1,不是二的幂答案就是是二进制长度。#includeint main(){ int n,kas = 0; while(scanf("%d",&n),n>0){ int r = 0; for(n...
阅读全文
摘要:用把失配边也加到正常边以后AC自动机,状态是长度递减的DAG,每次选一个不会匹配字符的转移。dp[u][L]表示当前在tire树上u结点长度还剩L时候不匹配的概率,根据全概率公式跑记忆化搜索。#includeusing namespace std;typedef double ld;const in...
阅读全文
摘要:二维的矩阵匹配,把模式矩阵按列拆开构造AC自动机,记录行号(为了缩点判断)。把T矩阵按行匹配,一旦匹配成功,在假想的子矩阵左上角位置加一。最后统计总数。因为所有模式串长度一样,不用维护last数组。模式串可能有重复,结点要用vector来存。HASH出奇迹,快得不行。。。#includeusing ...
阅读全文
摘要:AC自动机的裸题。学了kmp和Trie以后不难看懂。有一些变化,比如0的定义和f的指向,和建立失配边,以及多了后缀连接数组last。没有试过把失配边直接当成普通边(一开始还是先这样写吧)。#includeusing namespace std;const int maxlen = 1e6+5, ma...
阅读全文
摘要:kmp的代码很短,但是不太容易理解,还是先说明一下这个算法过程吧。朴素的字符串匹配大家都懂,但是效率不高,原因在哪里?匹配过程没有充分利用已经匹配好的模版的信息,比如说,i是文本串当前字符的下标,j是要匹配的模版串当前正在匹配的字符的下标。(下标都从零开始,j同时可以表示已经匹配的字符长度)当匹配到...
阅读全文
摘要:先两两比较,比较次数是两者相同的最长前缀长度*2+1,比较特殊的情况是两者完全相同时候比较次数是单词长度*2+2,两个单词'末尾\0'和'\0'比较一次,s尾部'\0'和循环内'\0'比较一次。因此,对于一个单词,只要知道和它某个相同的最长前缀的单词数就可以计算出方案数了。用tire,记录一颗子树上...
阅读全文
摘要:状态是DAG,因此方案用dp统计,dp[i] = sum(dp[i+len(x)]),x是以i开头的前缀且是单词,关键在于快速判断一个前缀是不是单词,可用Trie。每一次转移的复杂度是O(maxlen),maxlen是单词的最长长度。#includeusing namespace std;const...
阅读全文
摘要:题意:求一个动态区间的最大连续和。静态版本的O(n)算法显示不适用了,但是可以用线段树分治,因为一个连续和要在两边的区间,要么跨越两边,对于一个结点维护最大前缀和,后缀和,子区间连续和。题目要求输出区间,所以还要保存连续和最大的区间,以及前缀和,后缀和的位置。为了维护最大前缀和以及后缀和还需要一个区...
阅读全文
摘要:询问静态区间最值的Sparse—Table(Tarjan提出)的算法。这个算法的思想是一个dp,dp[i][j]表示i开头长度为2^j的区间内的最值,然后倍增转移。这道题询问的是出现次数,相同的数字是连续出现的,先把连续出现的数字按段编号,记录出现的次数。因为题目询问给的是原来的数字的下标,记录一下...
阅读全文
摘要:枚举中间的人,只要知道在这个人前面的技能值比他小的人数和后面技能值比他小的人数就能计算方案数了,技能值大的可有小的推出。因此可以利用树状数组,从左到右往树上插点,每个点询问sum(a[i]-1)就是前面的技能值比它小的人数,然后再从右边往左重复一遍就可以算出答案。#includeusing name...
阅读全文
摘要:简单题,题目要求显然是很多次插入,所以是链表。插入两个语句,nxt[i] = nxt[u] 表示 i结点指向u的后继, nxt[u] = i表示把u的后继设成i。设置一个头结点,指向一个不存在的结点,维护一下最后一个结点tail。#includeusing namespace std;const i...
阅读全文
摘要:题意:对一个矩阵进行子矩阵操作。元素最多有1e6个,树套树不好开(我不会),把二维坐标化成一维的,一个子矩阵操作分解成多条线段的操作。一次操作的复杂度是RlogC,很容易找到极端的数据(OJ上实测没有),如果判断一下然后启发式建树复杂度是min(RlogC,ClogR)。代码中结点没有保存l和r,而...
阅读全文
摘要:此题最难处理的操作就是将一个单点改变集合,而普通的并查集是不支持这种操作的。当结点p是叶子结点的时候,直接pa[p] = root(q)是可以的,p没有子结点,这个操作对其它结点不会造成任何影响,而当p是父结点的时候这种操作会破坏子节点的路径,因此必须保留原来的路径。我们希望pa[p] = root...
阅读全文
摘要:从包含k个整数的k个数组中各选一个求和,在所有的和中选最小的k个值。思路是多路归并,对于两个长度为k的有序表按一定顺序选两个数字组成和,(B表已经有序)会形成n个有序表A1+B1比较,而现在需要同时合并n个有序表,优先队列(堆)就派上用场了。类似归并排序用i和j维护有序表当前考虑元素,合并的时候,每...
阅读全文