摘要:神坑,精度要调到1e-10,板子没问题 /* 二分距离,凸包所有边往左平移这个距离,半平面交后看是否还有核存在 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #inc
阅读全文
摘要:想不明白这题写严格的半平面交为什么会错 /* 凸包所有边向内推进r */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #inclu
阅读全文
摘要:/* 二分距离,凸包所有边往左平移这个距离,半平面交后看是否还有核存在 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #inc
阅读全文
摘要:#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; #defin
阅读全文
摘要:这个模板用来判断多边形是否存在核(一点也行) 有个地方需要修改的 struct line{}里面的一个函数 int include(point k){return sign(cross(p[1]-p[0],k-p[0]))>=0;}//k在l左端 #include<iostream> #includ
阅读全文
摘要:一看题感觉像炮兵布阵类似的状压 写了半天发现是假的解法:这题有一个更强的限制就是要填满, 所以状压dp的话要用dp[i][s][ss]表示第i行的颜色状态和填色策略, 或者外层用3^n复杂度的枚举子集来做 算了一下这么一来时间复杂度就不对了O(3^n*2^n*n) 其实可以直接用dfs剪枝搜索 #i
阅读全文
摘要:用旋转卡壳的思想,固定住一点,然后剩下两点通过单峰函数的性质进行移动 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> using na
阅读全文
摘要:求两个凸包间的最小距离,最大距离,都是用同一种思路 最大距离:枚举凸包A的每条边,然后去B找对踵点,求的是点到点的最短距离 最小距离:比最大距离稍复杂一点,枚举凸包A的每条边,去B找对踵点,如果只有一个对踵点,那么求点到线段最短距离 如果有两个对踵点,那么求线段到线段的最短距离(需要改动一下disS
阅读全文
摘要:首先要了解对踵点的定义https://blog.csdn.net/qq_34921856/article/details/80689629 然后是旋转卡壳算法的全家桶 https://blog.csdn.net/qq_34921856/article/details/80690822 但是代码实现有
阅读全文
摘要:#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> using namespace std; #define N 3005 typedef
阅读全文
摘要:严格凸包的情况下,每条边上至少要有三个点,叫做稳定凸包 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> using namespace
阅读全文
摘要:注意剪枝一下,不然会t #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<algorithm> using namespace std; #define N
阅读全文
摘要:凸包性质 如果把凸包的一点放到原点,那么剩下所有点只会经过三个象限,且每个象限内的点极角递增或递减 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<v
阅读全文
摘要:博客链接 https://blog.csdn.net/commonc/article/details/52291822 #include<bits/stdc++.h> using namespace std; #define N 100005 typedef double db; const db
阅读全文
摘要:注意:对浮点数进行gcd时尽量吧eps设得大一点1e-2 /* 当圆外切给定三角形时,该圆最小 求三角形ABC外切圆的半径R S=0.5*ab*sinC a/sinA = b/sinB = c/sinC = 2R S=abc/4R => R=abc/4S 根据海伦公式 S=sqrt(p(p-a)(p
阅读全文
摘要:V-E+R=X+1: V:顶点数 E:边数 R:隔离的面数 X:连通图数量 对于圆来说:V=E=0, 当两圆相交时,V+2,E+4,两圆相切时V+1,E+2 圆的边数E=圆上点数 #include<bits/stdc++.h> using namespace std; #define N 10000
阅读全文
摘要:/* 通过c[i]和c[i+1]求出上一层圆的圆心 */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N
阅读全文
摘要:/* 枚举前面的圆,找到最远的相切位置即可 开头结尾的两种情况也不能忽略 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 2005 type
阅读全文
摘要:符合条件的串:最多只能有一个字符出现次数是奇数次 设置一个26位状态表示 字符i出现情况:0出现偶数次|1出现奇数次 i:0->n-1 求出s[0..i]所代表的状态mask, 设满足条件的一个前缀s[0..pre]的状态是mask1 那么 count(mask^mask1)<=1 所以只要把mas
阅读全文
摘要:/* 求出所有可能的向量V(x,y)使一个点集通过V移动后和新的点集合并,得到给定的点集 直接枚举1和其他点组成的向量即可 因为不管怎么平移,1肯定要有个对应的点,所以合法向量就从这里找即可 注意:得到的向量统一转换成x>0的向量,然后再*2就是答案 */ #include<bits/stdc++.
阅读全文
摘要:这题解决了我一直以来不明白的一个模型,就是将序列变成等差的最小代价 题库链接 https://www.jisuanke.com/contest/7652?view=challenges 2020 campday7 的I也是这个模型 /* 不妨假设:a[1]一开始就在第一个目标位置,那么整个序列就变成
阅读全文
摘要:#include<bits/stdc++.h> using namespace std; #define N 2005 typedef double db; const db eps=1e-6; const db pi=acos(-1); int sign(db k){if (k>eps) retu
阅读全文
摘要:碰到极角排序不能无脑就用双指针写,要思考是否有更加好的写法 本题由于有三点共线,所以双指针扫描会有问题,由于只要求直角个数,所以我们可以直接用lower_bound二分去找这个就可以 或者也可以用map重载point的=,<,>运算 #include<bits/stdc++.h> using nam
阅读全文
摘要:用对称的思想,每次极角排序前,把黑点按原点对称,就可以转换成为白点进行统计了 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std;
阅读全文
摘要:一道题弄了一整天。。 本题有一个坑:在每个圆覆盖的极角范围内,有的点因为离圆心近,还是不会被圆挡住,所以在判断圆能否挡住一个点时,还要再用点积判一下该点是否在切点,圆心,原点三角形内 收获:要慎重选择使用叉积进行排序还是直接用rad排序,前者精度高,后者实际用起来更加方便,本题要用到lower_bo
阅读全文
摘要:极角排序双指针扫描时一定要把数组扩展成两倍!这样写起来方便很多(惨痛教训) #include<bits/stdc++.h> using namespace std; #define N 200005 typedef double db; const db eps=1e-8; const db pi=
阅读全文
摘要:这个版本还不能处理三点共线的情况(处理起来其实比较麻烦) 可以用atan2来排序(较为简单,但是精度误差大),也可以用叉积排序(比较优秀) atan2 #include <iostream> #include <cstdio> #include <cstring> #include <algorit
阅读全文
摘要:感觉计算几何好多细节啊 这题的细节:障碍物在马路下面,在房子上面,都不用算 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #
阅读全文
摘要:计算几何里常用的套路:两两枚举点卡住,然后看是不是满足条件 poj上的题依然有很多坑,答案可能是负数,因为这个wa了好久 /* 枚举上端点i,下端点j,作为光线,那么max(i,j)以前的所有管道线段都不可以与该线相交 同时求出max(i,j)以后的最近的交点在哪里(或没有) */ #include
阅读全文
摘要:目前poj似乎数据出了问题,拿以前a的代码交上去也是wa 总体来说,要考虑三种答案0.00的情况 1.线段不相交 2.一根线段水平 3.开口被封闭,即高的那一端把低的那一端完全遮住了 #include<iostream> #include<cstring> #include<cstdio> #inc
阅读全文
摘要:#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 305 int n,a[N],b[N];//把边长当做中心到顶点的距离 int L[N],R[N]
阅读全文
摘要:/* 每次新选点时都要将上一个方向延长,作为新的x轴,然后将上一个点作为原点O,给剩下的点进行一次极角排序 极角排序:普通的极角排序要判断象限,但是本题不用判象限, 因为不难证明,所有剩下的点相对新坐标系,都在一,二象限内 如果还有点在第三,四象限,那么这些点应该被先访问到:所以cmp里只要进行一次
阅读全文
摘要:惨痛教训,这种排序在01背包里也有类似的题目,为啥比赛会想错呢 https://blog.csdn.net/the_love_story/article/details/52179575 /* 每个点i:有两个特征值a[i],b[i] 求两个点i,j,使min(a[i]+b[j],a[j]+b[i]
阅读全文
摘要:坑点: 1.要重新组织一下左上右下的坐标 2.在矩形内也算相交 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef double db; const db
阅读全文
摘要:有个地方要转化一下: 只能从中点炸开这个条件,实际上等价于从起点出发到终点要经过多少堵墙 因为所有墙都是直线,所以一旦在路上堵着永远绕不开,反正不在路上的墙不管从哪里进入都不会被碰到 所以不用枚举中点,直接枚举边上的端点,和终点连线,判严格相交即可 #include<iostream> #inclu
阅读全文
摘要:O(n2)的暴力居然能过。。 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 200005 #define db double const db
阅读全文
摘要:/* 两两枚举端点,如果线段不和任何一条线段相交,则连一条边,然后跑最短路 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; #d
阅读全文
摘要:#include <cstdio> #include <cmath> #define db double using namespace std; const db eps=1e-6; const db pi = acos(-1); int sign(db k){ if (k>eps) return
阅读全文
摘要:/* 线段和直线非严格相交:线段两点和直线的叉积 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 405 #define db double
阅读全文
摘要:#include<iostream> #include<cmath> #include<cstdio> #include<cstring> using namespace std; #define db double const db EPS = 1e-9; inline int sign(db a
阅读全文
摘要:/* 由于可以在一条边上反复横跳,所以只要考虑奇偶性和k够不够大的问题 a->b只有两种策略可以走: 直接走lca或者经过边(a,b),第二种只要让x->a,y->b或(x->b,y->a),然后再+1就是最短路径长度 */ #include<bits/stdc++.h> #include<vect
阅读全文
摘要:#define mp make_pair #define fi first #define se second #define pb push_back typedef double db; const db eps=1e-6; const db pi=acos(-1); int sign(db k
阅读全文
摘要:感觉这一题的状态设计很有讲究 一开始的思路是枚举s的前半部分,去贪心的匹配t串,然后再看剩余部分是否可以匹配t的后半部分 但这种思路显然是错的(样例都过不了),原因是可能t后半部分的某个特征串只在s中(对应的一个特征序列)出现了一次, 但是这个s中的特征序列由于被t前半部分贪心的匹配,被打破了,所以
阅读全文
摘要:#include<bits/stdc++.h> using namespace std; #define ll long long int n,m,k,tot; vector<char>v[10005];//先把连续动作放在v里 struct Step{ string s; int loop; St
阅读全文
摘要:/* 生成函数+FFT/NTT+容斥计数 求(i,j,k)组合,使得a[i],a[j],a[k]可以组成三角形 先给a排个序,然后用cnt数组统计, 假设以每条边a[k]作为最大边(不是数值最大,是排序后位置最靠右),剩下两条边就要满足a[i]+a[j]>a[k] 那么满足这个条件的对数就可以通过F
阅读全文
摘要:前置技能:原根的一些定理 https://www.cnblogs.com/Sakits/p/8416918.htm https://blog.csdn.net/ACdreamers/article/details/39026505l
阅读全文
摘要:系列博客 https://www.cnblogs.com/2016gdgzoi471/p/9476883.html FFT原理详解,包含大数乘法的代码 https://www.cnblogs.com/RabbitHu/p/FFT.html 多项式乘法:就是套一套板子: #include<iostre
阅读全文
摘要:/* 先把n二进制拆分,用map保存a[i]出现次数 然后从低位到高位去凑n 对于n某位是1的位数i 考虑mp里是否有1<<i 如果没有,考虑mp里比i低位的数能否凑出i, 如果还是没有,就从高位去拆,只有这种情况下,才会对答案有贡献 */ #include<bits/stdc++.h> using
阅读全文
摘要:/* 强连通缩点后得到一个拓扑图 把这个拓扑图取反,在图上进行dp,最后dp[s]就是答案 */ #include<bits/stdc++.h> using namespace std; #define N 2000006 #define ll long long struct Edge{ ll t
阅读全文
摘要:/* 结点i的左儿子是2i,右儿子是2i+1 那么显然这是一棵完全二叉树。 由于没有很好直接查询的办法,所以先考虑预处理一下这棵树 根据完全二叉树的性质,sum{size[i]}<=nlogn,所以直接用vector存下结点的所有孩子,自底向上对到子树距离归并排序 这样预处理完后,对于每个询问(A,
阅读全文
摘要:/* 不定方程 x1+...+xy=c 的正整数解有C(y+c-1,y-1)个 质因子分解后每种因子都独立算贡献,再相乘 最后因为可以随意加偶数个-1,所以再乘2^y-1 */ #include<bits/stdc++.h> using namespace std; #define ll long
阅读全文
摘要:/* 贪心策略: 如果检查的那天不用加,那就不加 反之加上尽可能多的钱 如何确定这个值? 处理出前缀和,第i天可以加的钱=d-[i+1,n]天里前缀和的最大值 加上这个值后,要再一次更新前缀和数组,用线段树维护前缀和数组即可 */ #include<bits/stdc++.h> using name
阅读全文
摘要:/* 从区间[l1,r1]取出一个数,这个数的期望值为 e1=(sum[r1]-sum[l1-1])/(r1-l1+1) 同理从区间[l2,r2]里取出一个数,这个数期望为 e2=(sum[r2]-sum[l2-1])/(r2-l2+1) 根据期望线性性,[l1,r1]里每个数被选中的概率是1/le
阅读全文
摘要:把模数写成了1e9+9,气死我了 /* 1-70里只有19个质数,首先考虑状压dp 第i个质数出现奇数次,那么第i位为1,反之为0 每个数在质因子分解后都可以得到一个对应的mask dp[i][s]表示当前选的数是i,且其状态为s时的方案数 那么选择偶数个i对s的状态无影响,有C(cnti,0)+C
阅读全文
摘要:大致思路是数位dp里当前位limit的那一套思想,从前往后递推计算,卡常数比较恶心 /* i:1->n 枚举第i位[a,z] 第i位<s[i]:那么后面就是个全排列,维护一个当前已经用掉的字符桶use,算出贡献直接加到答案里 算贡献:(n-i)!/(cnta-usea)!...(cntz-usez)
阅读全文
摘要:/* 给定数组a[],表示每种资源数目标量,一开始都是0 每次增,删,改一个三元组(s,t,u):如果资源s数量t,那么资源u+1,可链式增加 问每次修改后达到目标资源的最少用时 结论:直接开数组cnt[i]累计每种资源通过三元组增加的值,多出a[i]的部分去掉就是贡献 */ #include<bi
阅读全文
摘要:题解看这个https://blog.csdn.net/u013534123/article/details/78926568 状压的debug真的很烦 #include<bits/stdc++.h> using namespace std; int mask[5][5],n,a[5],dp[1010
阅读全文
摘要:模拟大讨论就完事了! #include<bits/stdc++.h> using namespace std; #define N 5005 int n,K,cnt[26],mx,tmp[26]; char s[N][N],t1[N],t2[N]; int judge(char *s,char *t
阅读全文
摘要:冲就完事了 /* 把每种颜色的数量统计出来,并求出最小的数量Min 从Min+1开始降序枚举s,暴力判就行了 */ #include<bits/stdc++.h> using namespace std; #define N 2000006 int n,a[N],tot; map<int,int>m
阅读全文
摘要:/* 首先求出multiset,设其大小是size,那么除数集合是[2,size+1] 对于multiset里面的某个余数x,其可能的除数集合就是[x+1,size+1] 将余数从大到小统计贡献 本题有一个坑:最后个余数的位置里不能填0,因为余数是0表示被除尽,那么商必不可能是0,所以其不可能是最后
阅读全文
摘要:细节很多,改了好久。。 /* 按阶梯状贪心填入字符,当第k行被填满后,再去填其他空位 */ #include<bits/stdc++.h> using namespace std; #define N 2005 char s[N*N],t[N*N],ans[N][N]; int n,l,k,len;
阅读全文
摘要:/* 题意:一棵有根树,每个结点的权重为2^i,每条边的权重为其下子树结点的权重和 现在按边权降序排序,每条边记录高度大的那个点,得到一个长度为n-1的序列 根据这个序列构造出一棵合法的树 性质:(fa[fa[u]],fa[u])必排在(fa[u],u)前面 可以自底向上构造这棵树,先把叶子结点放进
阅读全文
摘要:不知道为啥只开int会炸。。这题思维过程还是很有趣(痛苦)的 /* 01字典树求X异或最大值的策略就是X取反后去字典树里跑,跑到不能跑了就是答案 X在往01trie下搜时,如果碰到要去的地方是null,那么它只能朝另一个方向走, 同时最终异或起来的答案(即和X异或最大的那个值)损失了1<<(29-i
阅读全文
摘要:感觉自己的解法又是歪的 代码写的很乱。。要先找出一开始有多少段,然后计算删掉每条线段的贡献,求个最大值就可以 删每条线段的贡献可以用线段树区间合并来做 ps:正解其实很简单。。扫描一下就可以了 /* 先把所有线段覆盖到线段树上 然后对每一个线段[L,R],查询区间[L,R]有多少值>1的段即可 */
阅读全文
摘要:/* 二分bk,所有比bk大的数设置为1,比bk小的数设置为0 然后得到一个n*m的01矩阵,每行a的状态用s[i]表示,问题转换成判是否存在s[i]|s[j]=(1<<m)-1 再开一个flag[i]统计是否出现过状态i 然后暴力枚举是否存在这样的s[i]|s[j]=(1<<m)-1 */ #in
阅读全文
摘要:感觉自己的解法有点歪 /* 每次把一个数提到最前面,问整个过程结束后1..n每个数出现最靠前的位置和最靠后的位置 最靠前:如果一个数被提前过,那么必然是1 如果从来没被提前过,就是其原来的位置 最靠后:维护数i每次被提前的时间序列time[i][] time[i][1]到time[i][2]之间出现
阅读全文
摘要:/* 题意可以转化为通过s[l..r]构造出新的串t[l..r]和s不能约 t[l..r]的每个前缀,每个后缀的字符数量都必须和s[l..r]对应的前后缀字符数量不同 构造策略: 如果s[l]!=s[r]直接交换即可 否则找到s[i]!=s[j],swap(s[i],s[r]),swap(s[j],
阅读全文
摘要:一道很好的题了,具体题解可以看b站的讲解。。 拆点的思想有一种2sat的感觉 /* 给定一组开关的集合,每个开关最多被两个集合包含,对集合操作一次则所有集合内的开关状态变化 现在要将前i个开关状态切换到开,问最少要操作几次集合,求出i从1到n的每个答案 一些性质:每个集合要么被操作一次,要么不被操作
阅读全文
摘要:/** 给定一棵树,要求给树边赋值[0,n-2],每个值只能使用一次 S = mex(u,v), mex(u,v)是u-v路径上没有出现过的编号最小的值 问使得S最大的赋值方式 由于很难直接统计答案,所以考虑统计每条边的贡献 包含(0)路径的贡献tot1是其左右子树size的乘积 包含(0,1)的路
阅读全文
摘要:/* 给定一个数组,切割成pre,suf,现在要移动这两个集合中的元素,使 Max(pre)<Min(suf),且移动代价最小 对问题进行转化:移动后长度为len的pre,必定包含[1,len] 所以枚举移动前pre的长度,再考虑每个移动后pre长度的对应的代价 第二步可用线段树优化,每个结点维护移
阅读全文
摘要:暴力求出坐标在1e18范围里的点,然后依次枚举以i为起点,先收集小数据,再收集大数据的贪心策略 /* xi-x_i-1 = (ax-1)*x_i-1+bx yi-y_i-1 = (ay-1)*y_i-1+by ax,ay>=2,bx,by>=0 */ #include<bits/stdc++.h>
阅读全文
摘要:一开始以为是个模式匹配题,其实要先推出性质,就很好做了 /* 由于每列都具有独立性,所以一列一列计算答案 问题转化成给定一个数组a,要对其进行最小次数的循环上移或修改,最后匹配数组b 观察b数组的性质,我们发现第j列的数组b[j][] = {j+(i-1)m},为了方便处理,我们把第j列的a,b数组
阅读全文
摘要:/* 在树上找三个点,似的这三个形成的路径覆盖边数最多 结论:一定是直径+直径上最深的叶子 把直径拉出来,然后直径上每个结点dfs一次就可以 */ #include<bits/stdc++.h> using namespace std; #define N 400005 vector<int>G[N
阅读全文
摘要:/* d=(a,m),a=pd,m=qd,(p,q)=1 (pd+x,qd)=d,设x=td (pd+td,qd)=d => (p+t,q)=1 => (p',q)=1,p<=p'<p+q 处理出q的所有质因子,然后用这些质因子在区间[p,p+q-1]里筛 */ #include<bits/stdc
阅读全文