08 2017 档案
摘要:分块+二分 这道题思路很巧妙 我们大概可以推出一个式子sigma(d-[(ai-1)%d+1])<=k,要求求出d的最大值 然后我们化简一下,sigma(d-[(ai-1)-[(ai-1)/d]*d+1])<=k -> sigma(d-ai-[(ai-1)/d]*d)<=k 直接枚举肯定炸,但是我们
阅读全文
摘要:最小割 套路最小割。。。 盗一波图 来自GXZ神犇 对于这样的图,我们要么割ai,bj,要么割bi,aj,要么割ai,ci+cj,aj,要么割bi,ci+cj,bj,然后这样建图跑最小割就行了 但这不是重点,这道题我t了大概一个月,不知道为什么,怎么和别人比对代码好像没有什么差异,结果发现判断del
阅读全文
摘要:AC自动机+数位dp 先建立AC自动机trie图,然后在上面跑dp。 dp[i][j][0]表示到了天际线,也就是j==n时<n的方案数 dp[i][j][1]表示到了天际线并且==n的方案数 f[i][j]表示j<n时合法的方案数 因为如果位数比n小,那么我们不用在乎每位选什么,只要没有前导0就行
阅读全文
摘要:坐标轴转化+cdq分治 我们发现那个绝对值不太好搞,于是我们把曼哈顿距离转为切比雪夫距离,x'=x-y,y'=x+y,这样两点之间距离就是max(|x1'-x2'|,|y1'-y2'|),这个距离要小于等于k,那么就是求转化后坐标系中在以x',y'为中心,边长为2k的正方形中的点数,每次修改就相当于
阅读全文
摘要:背包+倍增 直接背包跑不过去,那么我们把容量分成二进制,然后原来需要枚举c次就只用枚举log(c)次了,这样还是能组合出任意小于等于c的组合方案 #include<bits/stdc++.h> using namespace std; const int N = 20010; int n, s; i
阅读全文
摘要:极角排序 先开始想了很多分割方法,发现都不对,最后觉得只能极角搞搞,就看了答案 我们发现,一个点的原点构成的直线把平面分成了两半,那么只由一边点和这个点构成的三角形肯定不包含原点,那么我们按极角排序,然后计算右边有多少点C(x,2)就行了。因为一个三角形有三个点,枚举到中间那个点的时候这个三角形不会
阅读全文
摘要:树形dp dp[x][0]表示x点父亲没选,dp[x][1]表示x点父亲选了,然后dp[x][0]=max(sigma(dp[c[x]][0]),sigma(dp[c[x]][1])) dp[x][1]=sigma(dp[c[x][0]]) 答案就是dp[1][0] 根没有父亲 #include<b
阅读全文
摘要:差分约束系统 1.du=dv 2.du+1<=dv 3.du>=dv 4.du>=dv+1 5.du<=dv 事实上,这道题希望总和最小,于是我们由小于号的左边连向右边,边权为常数项,跑最长路就可以了。 ①:对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路
阅读全文
摘要:A:开个桶统计一下,但是不要忘记k和0比较大小 #include<bits/stdc++.h> using namespace std; char s[1100]; int cnt[110]; int main() { int k; scanf("%s%d", s, &k); int n = str
阅读全文
摘要:高斯消元+矩阵的逆 来自popoqqq大神 求矩阵的逆:把I-T放在左边,P/Q*S放在右边,这样就形成了一个n*2n的矩阵,然后把左边高斯消元,右边就是求完逆的矩阵,其实就是ans,矩阵的逆跟乘法逆元是一样的,只不过是矩阵的逆元 然后输出a[i][n+1],事实上矩阵只有n*(n+1) 构造转移概
阅读全文
摘要:点分治/贪心 对于点分治的理解不够深刻...点分治能统计树上每个点对的信息,那么这里就是统计同种颜色点对之间的最大距离,自然可以用点分 然后点分,每次统计最大距离,但是略微卡常... 还有一种贪心的方法,每种颜色必然选以某点为根最深的节点,计算出最深的节点,然后dfs,看每种颜色,然后和最深的节点计
阅读全文
摘要:treap+并查集 我们能想到一个点和最近点对连接,用并查集维护,但是这个不仅不能求,而且还是不对的,于是就看了题解 把距离转为A(x-y,x+y),这样两点之间的距离就是max(x'-X',y'-Y'),那么就可以求了,我们按转换后的x排序,维护一个区间,最大的x和最小的x差不超过c,然后把y插进
阅读全文
摘要:二分+二分图匹配 晚上脑子不太好使。。。 行列模型,填充数量性质,种种迹象告诉我们这是二分图,但是我觉得好像不太科学就弃了网络流。。。 二分第k大值,转化为求第n-k+1小值,二分求匹配判定即可。 #include<bits/stdc++.h> using namespace std; const
阅读全文
摘要:哈希 cf原题。。。没见过的话真想不出来 将邻接表排序哈希,判断是否相同,但是会漏掉两点相邻的情况,于是再把自己加入自己的邻接表,然后再哈希判断。 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int
阅读全文
摘要:dp+树状数组 一维排序,一维离散化,然后跑lis,其实就是一个二维偏序 #include<bits/stdc++.h> using namespace std; const int N = 200010; int dp[N], tree[N]; struct data { int x, y, p;
阅读全文
摘要:高斯消元+搜索 很明显每个开关只能按一次,那么我们可以想到高斯消元,其实就是解异或方程组,但是最后会有一些自由元,也就是有x+y=z,x+y=z这种一样的方程就会产生自由元,那么我们爆搜自由元取值,每次把自由元回带入方程,因为形如x+y=z这样的方程就需要回带,然后就解出一组解,取最小值即可。这当然
阅读全文
摘要:二维单调队列 rmq很明显会超时,如果这个序列是一维的,很明显就是个单调队列,现在就是把一维的单调队列转换为二维单调队列。 先求出每一列的窗口极值,然后对于每一行做单调队列,值就是之前求出每个位置结尾的极值,这样就求出了每个正方形的极值。 写起来要注意一些。 #include<bits/stdc++
阅读全文
摘要:容斥原理+背包 首先每次做背包是不可行的,那么我们要优化一下,既然是有一些限制条件限制我们获得结果,我们就用容斥去弱化条件,也就是无视一些条件。 既然硬币是有限制的,那么我们就无视限制,用补集求答案,总方案-超限,但是超限也不好算,就用容斥,先跑完全背包求出总方案,然后减去一个超限,加上两个超限,减
阅读全文
摘要:竟然还涨分了。。。rank500+还能涨我rating是有多低。。。 AB不写了 C:类似找规律,具体证明看edtorial #include<bits/stdc++.h> using namespace std; const int N = 200010; int m; struct data {
阅读全文
摘要:背包+fft 既然要不选一个东西,那么我们求出前缀背包和后缀背包,每次答案就是f[i-1][w]*g[i+1][j-w] 但是这样复杂度还是n^3,跑不过,但是我们发现上面那个东西不就是个裸卷积吗,直接上fft,但是wa了... wa的程序,大概是精度问题吧 #include<bits/stdc++
阅读全文
摘要:哈希+拓扑排序 题意比较绕,先开始没看懂就看了发程序,发现好像理解的不太一样,后来找到了一个题目解释。。。 摘自jcvb:其实就是说颜色相同且三个出口分别对应相同(注意有可能是合并后才相同)两个结点是相同的,可以合并,求最后合并完后剩下几个结点。 所以我们倒着计算一个房间是否和以前相同,因为有可能合
阅读全文
摘要:LCT 昨天调试一天没出来,今天推倒重写还是gg了,内心崩溃照着源代码抄,结果发现自己把原树fa和splay的fa一起维护,各种re。。。 其实我们手玩一下,发现其实树的形态变化很小,那么就可以用lct维护了,查询就是相当于查询点到root的点权和,点权为1 删除什么的手画一下就行了 然后我们要用一
阅读全文
摘要:树的直径 我先开始以为是个图,想想并不知道什么求图的直径的方法,结果是棵树 那么直觉告诉我们是在直径上面,实际上就是直径+min(i->u,i->v),扫一遍就行了 #include<bits/stdc++.h> using namespace std; const int N = 200010;
阅读全文
摘要:单调栈 其实是单调栈的变种 维护up,left,right,表示一个点能向左向右向上最大扩展距离,ans就是最大的left*rigth*up up[i][j]=Map[i-1][j]==1?1:Map[i-1][j]+1 left和right 用单调栈求,每次碰见障碍就把栈中元素弹出,栈中元素左端点
阅读全文
摘要:splay维护dfs序 我们发现有移动子树这种操作,树剖是做不了了,又要实现子树加,lct又维护不了了,这时我们用splay维护入栈出栈序来支持这些操作。我们记录每个点的入栈时间和出栈时间,这样一个闭合的区间就表示了一个节点的子树,于是我们可以支持更换父亲了。然后是子树加,这里我们把要加的区间提取出
阅读全文
摘要:LIS+贪心 因为是要字典序尽量的小,但是如果我们从头做,就无法判断选了这个是否能够>=l,那么我们倒着跑一遍LDS,然后每次从尾部贪心,如果这个能选就选,判断标准是cnt+dp[i]>=l,就是已经选的加上这个的LDS比L大就是可以选。 #include<bits/stdc++.h> using
阅读全文
摘要:搜索 。。。大家都说这是水题。。。我没做出来。。。因为我以为分割不一定要等分 事实上每次切割都要分成当前需要块数的整数倍,比如说需要分成k块,那么肯定只能在k,2k,3k这里切,否则两边不成整数比,因为我们要把当前分成k块,所以只能这样切,然后就好做了,枚举分割点,横着竖着爆搜。 #include<
阅读全文
摘要:AC自动机+dp+矩阵乘法 我们先对串建立AC自动机,然后进行dp+矩阵乘法。AC自动机加上trie图优化,root的每个儿子如果没有就都填上,然后建立矩阵,mat[child[u][i]][u]=1,如果在trie图上child[u][i]是u的儿子,并且u和儿子都不是危险节点,然后初始值是dp[
阅读全文
摘要:splay+二分+哈希 splay维护区间哈希值,每次二分长度 调了很长时间,主要是两个错误:1.提取区间应该是pos+1,pos+2,因为现在在开头放了一个?,所以现在应该是位置比pos+1大,比pos+2小 2.二分边界,因为多加了两个字符,所以原串长度应该是cnt-2,那么二分边界应该是-1-
阅读全文
摘要:A:暴力模拟,能加就加,如果累计到了8就加上,每次累积 #include<bits/stdc++.h> using namespace std; int main() { int n,k ,cnt = 0; scanf("%d%d", &n, &k); for(int i = 1; i <= n;
阅读全文
摘要:最小生成树+最小割 。。。我太zz了,没看出来全体减1是一个加1,看见后就是sb题了。。。 我们发现根据克鲁斯卡尔的过程,我们把边从小到大加入,如果两点已经相连就跳过,那么我们把所有小于等于这条边的边加入,如果能够联通这两点,那么说明得增加一些边的权值,所以我们求出和这条边的差+1,连边,使得没有一
阅读全文
摘要:最小生成树 其实这道题是最小生成树的变种,我们发现答案不一定在最小/最大生成树上,最短路算法也不可行,因为我们我们并不是希望最小值尽量的大,最大值尽量的小,这样不一定是最优的,那么我们枚举最小的边,然后将大于他的边依次加入,直到联通,每次求出最大的边和枚举的最小边就是当前答案,更新即可。最大/最小生
阅读全文
摘要:可并堆 复习一下可并堆 维护一个大跟堆,每次把节点儿子打上边权标记,然后合并,可并堆上维护一个size,每次把大于l的弹出,size就是答案 程序中那个d写l和r速度差不多,我写l是表示右儿子到u的最长距离 #include<bits/stdc++.h> using namespace std; c
阅读全文
摘要:AC自动机+树链剖分+线段树/树状数组+dfs序+树链的并 题意:给出n个母串和q个询问串,对于每个询问串输出有多少个母串包含这个询问串 N=∑|母串|<=10^5 Q=∑|询问串|<=3.6*10^5 由于是母串包含询问串,那么我们就对询问串建自动机,然后用母串在上面跑,跑一次的复杂度是母串的长度
阅读全文
摘要:后缀数组+st表+分块+离散化 警告!!!博主内心已经崩溃啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阅读全文
摘要:费用流+线性规划 搞了很长时间。。。 我们可以设立式子,a[1]+a[2]+a[3]+...+a[n]<=k , ... , a[2 * n + 1]+ ... +a[3*n]<=k a是指该位有没有选 那么我们添加一个辅助变量f a[1]+a[2]+a[3]+...+a[n]+f[1]=k, ..
阅读全文
摘要:费用流 和3280很像,先建出上下界模型,然后转为普通费用流模型 s->1 flow=inf, c = f s->i+n flow=x,c=0; i->t,flow=x,c=0 i->i+1 flow=inf, c=0; i+n->i+n+1,flow=inf,c=0 i->i+a+1,i->i+b
阅读全文
摘要:费用流 建图:建立源汇s,t,对于每天建立两个点,live和dead,live向dead连接下界为a[i],上界为a[i],费用为0的边,表示一天需要只a[i]个人,也就是一天必须死a[i]个人,然后源点向第一天连上所有l[i],b[i],每天live连向下一天,容量为inf,费用为0,表示一天没有
阅读全文
摘要:有上下界的费用流 建图:每条边连接两个节点,边的费用为花费时间,下界为1,上界正无穷,源点为1,所有点连向1,下界0,上界正无穷,表示随时可以返回,于是我们想求一个最小费用可行流 具体做法是先建立超级源汇,对于每条有上下界的边(u,v),u->t,流量为u的入度,费用为0,s->v,流量为下界1,费
阅读全文
摘要:高精度 我以为这题必有高论,怎么想也想不出来,没想到竟是如此粗鄙做法。 我们写一个高精度模拟一下,然后枚举约数看是否能约分,由于我不会高精度除法,就抄了一发 其实这种两项之比和项数有关的数列是不能推通项的,只能暴力模拟 #include<bits/stdc++.h> using namespace
阅读全文
摘要:扩展欧几里得 我们发现其实就是两个野人在自己的寿命内不会相遇,或者永远不会相遇,那么我们枚举m,然后枚举两个人,看是否符合条件 扩展欧几里得ax+by=c,这里c不能取模,a能取模,具体不想了 #include<bits/stdc++.h> using namespace std; const in
阅读全文
摘要:离散化+树状数组+排列组合 很久以前就看到过这道题,现在依然不会做。。。看完题解发现思路很简单,就是有点难写 我们先将坐标离散化,x和y最大是w,然后我们就有了一个暴力做法, 枚举每块墓地,统计,因为墓地上下左右没东西的话就不可能有贡献,这些坐标自然就被离散化了,所以墓地最多有w*w块 复杂度O(w
阅读全文
摘要:exgcd 由于忘记了exgcd,这道题就没做出来。。。 exgcd的用处是求ax+by=gcd(a,b)这样方程的解 大概是这个样子的 void ext_gcd(long long a, long long b, long long &x, long long &y) { if(b == 0) {
阅读全文
摘要:贪心 这并没有想清楚就看题解了。。。 看上去肯定是贪心,那么怎么贪呢?事实上,我们想一下,假设max(a[i],a[i+1])中a[i]没有合并,那么后面取max肯定是a[i+1],因为如果后面合并之后比a[i+1]大,那么不如先和a[i]合并了,如果后面合并了比a[i+1]小,那么也没用,因为不可
阅读全文
摘要:AC自动机 复习一下。。。 可惜又写错了 我们发现就是把单词建成ac自动机,然后把串在ac自动机上跑一遍,每到一个单词结束点就删除,删除是利用栈,每次弹出单词长度个字符就可以了 发现两个小问题,strlen很慢,不能写在循环里,danger必须在构造fail时全部传递好,否则在匹配时跑fail会达到
阅读全文
摘要:模拟+树状数组 先开始以为是先删距离最小的,这样可以减小上下的距离,然后觉得很难写,看码长很短,就看了题解,结果很奥妙 我们只考虑两种元素,就是如果像-a-b-a-b-这样的肯定得交换,如果像-a-b-b-a-或-a-a-b-b-这样的就不用交换,于是我们对于每个元素考虑其他元素,也就是统计两个相同
阅读全文
摘要:treap+stl 这道题终于A了 排名是按照分数为第一关键字,插入时间为第二关键字,然后就是treap基本操作了 #include<bits/stdc++.h> using namespace std; const int N = 250010; int n, Tim, root, score,
阅读全文
摘要:二分+分数规划+dfs判环 跟1486很像,但是我忘记怎么判环了, 我们可以写一个dfs,如果当前节点的距离小于更新的距离,而且这个点已经在当前访问过了,那么就是有环了,如果没有访问过就继续dfs,每个点枚举dfs就行了。 如果这个点距离大于更新距离,那么没必要访问,因为刚才都没有判出来正环,现在这
阅读全文
摘要:树链剖分+二分+线段树套treap 写题5分钟,调试2小时。。。 很好理解,就是维护树链剖分的线段树改成线段树套treap,然后每次树套树删除一个数,插入一个数,二分一个数查找排名就行了 #include<bits/stdc++.h> using namespace std; const int N
阅读全文
摘要:带修改莫队 抄了个板子,跟莫队很像 莫队是两维排序,带修改的莫队是三维排序,(block[l],block[r],time) 我们把询问按照这个顺序排序,然后像普通莫队一样转移,唯一不同的是块要开到sqrt(n),还有转移区间之前要把对应区间的修改修改好,用一个cur指针指向当前修改,如果这个修改在
阅读全文
摘要:并查集+dfs 先开始想和不相连的点用并查集连起来,最后看每个连通块有多少个点就行了,但是这样是O(n*n)的,然而我并没有想到补图 其实就是求补图有多少连通块,因为补图中两个点有边,那么这两个点必须在一栋大楼里,因为他们之间没有联系,然后这样就有了许多连通块,不同的连通块可以不相连,因为不同的连通
阅读全文
摘要:线段树分治+并查集 跟1018很像,但是这里是带权并查集,修改时要注意,因为可回溯并查集不能路径压缩,所以也不能对保存到根路径长度的数组修改,每次连接,我们只对根的距离数组修改,这样不会影响操作结果,因为路径压缩就是把我们要求的d数组在find时把整个路径上的d数组都顺便修改了,这里我们用到哪个就求
阅读全文
摘要:并查集+最小生成树 首先我们发现这题可以lct维护最小生成树,但是发现如果生成树在之后是不会修改的,那么就想到了并查集,然后就不知道怎么做了。。。 其实当我们连接两个连通块的时候,两个连通块只能通过这一条边联通,所以这条边的两个端点是谁并不重要,因为两个连通块之间的通道最小值不会受到位置的影响。那么
阅读全文
摘要:线段树分治+并查集 线段树本身就是分治结构,碰见这种带删除修改的题目是再合适不过的,我们对于每段修改区间在线段树上打标记,每次路过就进行修改,叶子结点表及答案,先把所有修改在线段树上标记,然后dfs就行了 但是并查集怎么恢复呢?我们只要维护一个栈,保存某次操作之前这两个点的信息,dfs本身就是利用栈
阅读全文
摘要:线段树合并+离线+启发式合并 半年前这道题t成狗。。。 离线的做法比较好想,按照边的权值排序,询问的权值排序,然后枚举询问不断加边,加到上限后查找第k大值,这里平衡树,权值线段树都可以实现。 那么我们用权值线段树就行了, 并查集维护两点连通性,不连通的话就合并,并查集连接。 #include<bit
阅读全文
摘要:A:读懂题,乘一下判断大小就行了 #include<bits/stdc++.h> using namespace std; int main() { int s, v1, v2, t1, t2; scanf("%d%d%d%d%d", &s, &v1, &v2, &t1, &t2); int ans
阅读全文
摘要:A: 如果n%2=0或2就是undefined,否则判一下转一下是否能到达状态 #include<bits/stdc++.h> using namespace std; int n; char s[10], t[10]; int main() { scanf("%s%s%d", s, t, &n);
阅读全文