nxt

倍增&矩阵乘法 专题复习

柔情痞子 提交于 2019-12-01 22:57:03
倍增&矩阵乘法 专题复习 PreWords 这两个基础算法我就不多说啦,但是还是要介绍一下" 广义矩阵 "乘法 其实就是把矩阵换成取 \(max\) ,然后都一样。。。 据神仙LBC说:这不显然是对的吗! \[ \ \] \[ \ \] [usaco2007 Nov] relays 奶牛接力跑 离散一下,然后套矩阵乘法 \(a[i][j]\) 记录从 \(i\) 出发到 \(j\) 的最小答案,快速幂即可 const int N=410,P=1e4+7; int n,m,s,t; int a[N],b[N],c[N]; int h[N],cnt; inline void chk(ll &a,ll b) { ((a>b)&&(a=b)); } struct Mat{ ll a[N][N]; void init(){ memset(a,63,sizeof a); } Mat operator * (const Mat x) const { Mat res; res.init(); rep(i,1,cnt) rep(j,1,cnt) rep(k,1,cnt) chk(res.a[i][k],a[i][j]+x.a[j][k]); return res; } } res,x; int main() { n=rd(),m=rd(),s=rd(),t=rd(); rep(i,1,m) { c

题解 P1081 【开车旅行】

不想你离开。 提交于 2019-12-01 22:19:49
Solution 开车旅行 题目大意:有 \(n\) 座城市,每座城市有一个海拔高度,你只能从编号小的往编号大的移动。定义两城市距离为海拔高度差的绝对值。小A开车会去离他第二近的城市,小B开车会去离他最近的城市。(如果距离相同则认为海拔低的近)。两人开车的距离之和不能超过 \(X\) ,问给定一个 \(X\) 从哪座城市出发小A小B行驶距离之比最小,(一样小的认为海拔高的小),问给定出发点 \(s\) 和 \(X\) ,小A小B分别行驶距离 倍增 分析:首先关键在于给定 \(s\) 和 \(X\) 的时候快速算出他俩分别走了多远,这样第一问就可以枚举来回答 不难想到暴力算法,我们把A,B都走一次称为一轮,那么我们一轮一轮的走,直到走不动为止。因为A先走所以最后单独考虑A即可 这样的时间复杂度单次 \(O(n)\) ,无法承受。我们关注点在一轮一轮的走太花时间,因此我们可以倍增来走,单次时间复杂度降至 \(O(logn)\) 麻烦的地方在于预处理A和B会走到哪儿,不难想到,假如我们对于序列每一个后缀建一棵平衡树,那么小B就是在前驱和后继里面取最优。小A就是加上前驱的前驱,后继的后继然后取次优,这个我们用 \(set\) 来维护, \(vector\) 暴力排序即可(反正最多只有 \(4\) 个元素) 然后关于倍增,我们预处理出从每个位置 \(pos\) 走 \(2^i\)

hihoCoder#1879 : Rikka with Triangles (计算几何)

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-01 18:37:37
n<=2000,肯定没有办法把所有三角形找出来全判一遍 对于三角形的三个角,分别计算贡献,锐角的贡献是1倍面积,钝角的贡献是-2倍面积,这样算出角的贡献之后除以3就可以了 每次选择一个点为中心点,极角排序,维护一个锐角和钝角的坐标和,边扫边算贡献 #include <bits/stdc++.h> #define ll long long #define big __int128 #define eps 1e-8 #define mod 998244353 using namespace std; const int maxn = 2005; int sgn(double x) { if (fabs(x) < eps) return 0; if (x < 0) return -1; return 1; } struct Point { big x, y; Point() {} Point(big _x, big _y) { x = _x; y = _y; } Point operator+(const Point &b) const { return Point(x + b.x, y + b.y); } Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); } big operator*

Codeforces Global Round 5 补题记录

杀马特。学长 韩版系。学妹 提交于 2019-12-01 16:48:01
D 题意: 一个序列a,对每个a[i]会循环向后走,直到找到第一个 \(a[j\%n]<\frac{a[i]}{2}\) ,问每个a[i]最多走几步. 思路: 把a重复三遍(每个a[i]最多走2*n,否则为-1),对于a[i]被卡有两种情况,要么他后面有 \(a[j\%n]<\frac{a[i]}{2}\) ,要么是a[j]>a[i],这样a[j]更容易比a[i]卡,具体怎么维护看注释吧 #include<bits/stdc++.h> #define ll long long #define pii pair<int,int> using namespace std; int main(){ int n; cin >> n; vector<int> a(3*n); for(int i=0;i<n;++i){ cin >> a[i]; a[i+n] = a[i+n+n] = a[i]; } vector<int> ans(3*n); vector<int> st_max,st_min; for(int i=3*n-1;i>=0;--i){ while(st_max.size() && a[st_max.back()] < a[i]) st_max.pop_back(); // 单调减 while(st_min.size() && a[st_min.back()] > a[i]) st

【CF1237D】Balanced Playlist(set,二分,线段树)

♀尐吖头ヾ 提交于 2019-12-01 16:21:39
题意:给定一个n首歌的播放列表,第i首的值为a[i],听完第i首会回到第1首 现在从每首开始往下,记录听过的最大值,如果当前听的值严格小于听过最大值的一半则停止 问从每首歌开始往下听能听几首,不会停止则输出-1 n<=1e5,1<=a[i]<=1e9 思路:会D不会C,D的写法还奇渣无比…… 因为是环形所以先复制粘贴一遍,然后按a[i]从大到小排个序 对于每个出发点now,设在now之后且离now最近的值比他a[now]的点为nxt,在到达nxt之前其听过的最大值一定为a[now] 如果在now后面的最小值*2>=now后面的最大值则ans[now]=-1 如果now能到达nxt则答案即为ans[nxt]+nxt-now 否则可以二分出第一个不合法的点last,答案即为last-now 对于nxt集合用set维护,对于二分找到第一个不合法的点应该可以在线段树上二分做到一个log,我懒直接外面二分了,两个log 赛场上WA了一发,后面用自己的数据调出来了,今天一看和官方数据一样……我与出题人心意相通 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6

CF627E Orchestra [矩阵计数]

落爺英雄遲暮 提交于 2019-12-01 10:21:24
也许更好的阅读体验 \(\mathcal{Description}\) 题目大意 有一个 \(r * c\) 的矩阵上有 \(n\) 个点,问有多少个子矩阵里包含至少 \(k\) 个点 输入格式 第一行四个数 \(r,c,n,k\) ,接下来 \(n\) 行,每行两个数 \(x_i,y_i\) ,表示第 \(i\) 个点的坐标 输出格式 一行一个数表示合法子矩阵个数 数据范围 \(1\leq r,c,n\leq 3000 , 1\leq k\leq \min(n,10)\) \(\mathcal{Solution}\) 这题好难 题目要求至少包含了 \(k\) 个点的子矩阵, \(k\) 很小 朴素的想法是枚举上边界,下边界,然后在中间尺取,这样是 \(O\left(n^3\right)\) 的 反过来考虑,从下往上枚举每一行 先算出以这一行的每个顶点为左上角,最下面一行为第 \(c\) 的所有合法矩阵个数 计算方法考虑尺取即可 再考虑最下面一行逐渐往上走的合法矩阵个数 这个过程中,点是在不断变少的 考虑算出将最下面一行变为其上面那一行时合法矩阵的减少量,再用原来的合法矩阵量减去就是最下面一行往上移一行后的合法矩阵数量 如何计算合法矩阵的减少量 枚举这一行中的每个点,计算出包含这个点且点数刚好为 \(k\) 的矩阵个数,然后 删去这个点 计算方法也是尺取,另外

【2019 CCPC 秦皇岛】J - MUV LUV EXTRA

限于喜欢 提交于 2019-12-01 10:07:33
原题: 题意: 给你两个整数a和b,再给你一个正小数,整数部分忽略不计,只考虑小数部分的循环节,对于所有可能的循环节,令其长度为l,在小数部分循环出现的长度为p,最后一个循环节允许不完整,但是缺少的部分不计入循环长度 问你a*p-b*l的最小值是多少 考虑的循环节必须至少在小数部分中出现一次,小数部分的前缀可以不属于循环部分 这题也是一眼很棘手,和后缀数组和后缀自动机似乎都有相似之处 但是实际做法是kmp 翻转原串是关键思路,这样保证了能把原串前缀的不是循环部分的部分忽略掉,从而方便地利用next数组的性质 把小数部分串反过来,那么这个串的前缀就一定是循环部分 因为最后循环节允许不完整,所以考虑把一个循环节分成AB两部分,其中B是最后一个循环节缺的部分 考虑next数组的性质:next[i]表示子串[1,i]最长的前后缀长度,使得此长度的前后缀相等 那么对于ACA形式的串,其中A指最长的相同前后缀,把C接到A后边就可以变成ACA(C)的循环形式,前后缀有相交情况时同理 对于循环部分[1,i],出现长度就是i,出现长度固定,只需求出此时长度最小的循环节 由next的性质,保证[1,i-next[i]]是最小的循环节 可以反证,考虑ABABABABA,如果它被i-nxt[i]和next[i]+1划分为ABA BAB ABA,即认为[1,6]和[4,9]是相同的前后缀

2019牛客国庆集训派对day1-Distinct Substrings(扩展KMP)

Deadly 提交于 2019-12-01 07:46:35
题意描述 核心: 总感觉题目描述有问题,把s1看出是字符, s1...sn组成一个字符串,h(s,c)表示字符s末尾添加一个字符c的时候,字串的数目; 增加的字串可以看成是以字符C结尾的后缀;s1..sn颠倒之后看出字符串(sn..s1)T串,对于CT串,我们求出CT与T各个位置的最大公共前缀,就得出了共有的字串部分;这个我们可以借助扩展kmp来求,nxt[i]表示T[i-(n-1)]与T之间公告前缀部分,求CT与T[i]的公共前缀,若T[i]为字符C, 则CT[i+1]与CT公共前缀是nxt[i+1] 代码 #include <bits/stdc++.h> using namespace std; typedef long long LL; #define mod 1000000007 const int N=1e6+7; int x[N],w[N],nxt[N]; int n,m; void pre_exkmp() { nxt[0]=n; int j=0; while(j+1<n&&x[j]==x[j+1])j++; nxt[1]=j; // 从一开始,nxt[i-k]确实要前进 int k=1; for(int i=2;i<n;i++) { int p=nxt[k]+k,t=nxt[i-k]; if(i+t<p)nxt[i]=t; else { j=p-i<0?0:p-i;

hdu 4758 (AC自动机)

非 Y 不嫁゛ 提交于 2019-12-01 06:21:57
除了走到哪里,还要加状态表示当前节点和已经匹配的串 #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define lson l,m,rt<<1 #define pi acos(-1) #define rson m+1,r,rt<<1|1 #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define eps 1e-8 using namespace std; const int maxn = 250,maxs = 5; const ll inf = 1e9; const ll mod = 1000000007; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<

hdu 4511 (AC自动机)

你。 提交于 2019-12-01 06:12:50
注意标记一个点后,fail树上的子节点都会被标记 跑spfa,dp也可以 #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define lson l,m,rt<<1 #define pi acos(-1) #define rson m+1,r,rt<<1|1 #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define eps 1e-8 using namespace std; const int maxn = 50050; const ll inf = 1e9; const ll mod = 998244353; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&