吉林省赛及东北四省赛 模板
目录
线段树
区间和,单点修改
#include <bits/stdc++.h>
typedef long long LL;
const int maxn = 500000;
using namespace std;
struct tTree
{
LL sum;
int l, r;
};
tTree tree[maxn*4+10];
void pushup(int x)
{
if(tree[x].l == tree[x].r)
return;
tree[x].sum = tree[x*2].sum +tree[x*2+1].sum;
}
void build(int x, int l, int r)
{
tree[x].l = l; tree[x].r = r;
if(tree[x].l == tree[x].r)
scanf("%lld", &tree[x].sum);
else
{
int mid = (l+r)/2;
build(x*2, l, mid);
build(x*2+1, mid+1, r);
pushup(x);
}
}
void modify(int x, int pos, int val)
{
if(tree[x].l == tree[x].r)
tree[x].sum += val;
else
{
int mid = (tree[x].l+tree[x].r)/2;
if(pos <= mid)
modify(x*2, pos, val);
else
modify(x*2+1, pos, val);
pushup(x);
}
}
LL query(int x, int l, int r)
{
if(tree[x].l>=l && tree[x].r<=r)
return tree[x].sum;
else
{
int mid = (tree[x].l+tree[x].r)/2;
LL ret = 0;
if(mid >= l)
ret += query(x*2, l, r);
if(mid+1 <= r)
ret += query(x*2+1, l, r);
return ret;
}
}
int main()
{
int N, M;
scanf("%d%d", &N, &M);
build(1, 1, N);
for(int i=1,op,x,y; i<=M; i++)
{
scanf("%d%d%d", &op, &x, &y);
if(op == 1)
{
modify(1, x, y);
}
if(op == 2)
{
printf("%lld\n", query(1, x, y));
}
}
return 0;
}
区间和,区间修改
#include <bits/stdc++.h>
typedef long long LL;
const int maxn = 500000;
using namespace std;
struct tTree
{
LL sum, tag;
int l, r, len;
};
tTree tree[maxn*4+10];
void pushup(int x)
{
if (tree[x].l == tree[x].r)
return;
tree[x].sum = tree[x*2].sum + tree[x*2+1].sum;
}
void pushdown(int x)
{
if (tree[x].l == tree[x].r)
return;
LL tag = tree[x].tag;
tree[x].tag = 0;
tree[x*2].sum += tag*tree[x*2].len;
tree[x*2+1].sum += tag*tree[x*2+1].len;
tree[x*2].tag += tag;
tree[x*2+1].tag += tag;
}
void build(int x, int l, int r)
{
tree[x].l = l; tree[x].r = r;
tree[x].tag = 0;
tree[x].len = r-l+1;
if (tree[x].l == tree[x].r)
scanf("%lld", &tree[x].sum);
else
{
int mid = (l+r)/2;
build(x*2, l, mid);
build(x*2+1, mid+1, r);
pushup(x);
}
}
void modify(int x, int l, int r, int val)
{
if (tree[x].l>=l && tree[x].r<=r)
{
tree[x].tag += val;
tree[x].sum += val*tree[x].len;
}
else
{
pushdown(x);
int mid = (tree[x].l+tree[x].r)/2;
if (mid >= l)
modify(x*2, l, r, val);
if (mid+1 <= r)
modify(x*2+1, l, r, val);
pushup(x);
}
}
//the sum of the intersection of tree[x].l-tree[x].r and l-r
LL query(int x, int l, int r)
{
if (tree[x].l>=l && tree[x].r<=r)
return tree[x].sum;
else
{
pushdown(x);
int mid = (tree[x].l+tree[x].r)/2;
LL ret = 0;
if (mid >= l)
ret += query(x*2, l, r);
if (mid+1 <= r)
ret += query(x*2+1, l, r);
return ret;
}
}
int main()
{
int N, M;
scanf("%d%d", &N, &M);
build(1, 1, N);
for (int i=1,op,x,y,k; i<=M; i++)
{
scanf("%d", &op);
if (op == 1)
{
scanf("%d%d%d", &x, &y, &k);
modify(1, x, y, k);
}
if (op == 2)
{
scanf("%d", &x);
printf("%lld\n", query(1, x, x));
}
}
return 0;
}
区间乘加
#include <bits/stdc++.h>
typedef long long LL;
const int maxn = 100000;
using namespace std;
int N, M; LL P;
struct tTree
{
LL sum, mul, add;
int l, r, len;
};
tTree tree[maxn*4+10];
void pushup(int x)
{
if (tree[x].l == tree[x].r)
return;
tree[x].sum = (tree[x*2].sum + tree[x*2+1].sum)%P;
}
//changes of sum, mul, add
void pushdown(int x)
{
if (tree[x].l == tree[x].r)
return;
LL mul = tree[x].mul;
LL add = tree[x].add;
tree[x].mul = 1;
tree[x].add = 0;
tree[x*2].sum = (tree[x*2].sum*mul%P + add*tree[x*2].len%P)%P;
tree[x*2+1].sum = (tree[x*2+1].sum*mul%P + add*tree[x*2+1].len%P)%P;
tree[x*2].mul = tree[x*2].mul*mul%P;
tree[x*2].add = (tree[x*2].add*mul%P + add)%P;
tree[x*2+1].mul = tree[x*2+1].mul*mul%P;
tree[x*2+1].add = (tree[x*2+1].add*mul%P + add)%P;
}
void build(int x, int l, int r)
{
tree[x].l = l; tree[x].r = r;
tree[x].len = r-l+1;
tree[x].mul = 1; tree[x].add = 0;
if (l == r)
scanf("%lld", &tree[x].sum);
else
{
int mid = (l+r)/2;
build(x*2, l, mid);
build(x*2+1, mid+1, r);
pushup(x);
}
}
void modify(int x, int l, int r, int op, int val)
{
//keep the sum right
if (tree[x].l>=l && tree[x].r<=r)
{
if (op == 1)
{
tree[x].sum = tree[x].sum*val%P;
tree[x].add = tree[x].add*val%P;
tree[x].mul = tree[x].mul*val%P;
}
if (op == 2)
{
tree[x].sum = (tree[x].sum+tree[x].len*val)%P;
tree[x].add = (tree[x].add+val)%P;
}
}
else
{
pushdown(x);
int mid = (tree[x].l+tree[x].r)/2;
if (l <= mid)
modify(x*2, l, r, op, val);
if (mid+1 <= r)
modify(x*2+1, l, r, op, val);
pushup(x);
}
}
LL query(int x, int l, int r)
{
if (tree[x].l>=l && tree[x].r<=r)
{
return tree[x].sum%P;
}
else
{
pushdown(x);
int mid = (tree[x].l+tree[x].r)/2;
LL ret = 0;
if (l <= mid)
ret = (ret+query(x*2, l, r))%P;
if (mid+1 <= r)
ret = (ret+query(x*2+1, l, r))%P;
return ret%P;
}
}
int main()
{
scanf("%d%d%lld", &N, &M, &P);
build(1, 1, N);
for (int i=1,op,x,y,k; i<=M; i++)
{
scanf("%d", &op);
if (op == 1)
{
scanf("%d%d%d", &x, &y, &k);
modify(1, x, y, 1, k);
}
if (op == 2)
{
scanf("%d%d%d", &x, &y, &k);
modify(1, x, y, 2, k);
}
if (op == 3)
{
scanf("%d%d", &x, &y);
printf("%lld\n", query(1, x, y));
}
}
return 0;
}
区间最大值,无修改
#include <bits/stdc++.h>
const int maxn = 100000;
using namespace std;
struct tTree
{
int mmax;
int l, r;
};
tTree tree[maxn*4+10];
void pushup(int x)
{
if (tree[x].l == tree[x].r)
return;
tree[x].mmax = max(tree[x*2].mmax, tree[x*2+1].mmax);
}
void build(int x, int l, int r)
{
tree[x].l = l; tree[x].r = r;
if (tree[x].l == tree[x].r)
scanf("%d", &tree[x].mmax);
else
{
int mid = (l+r)/2;
build(x*2, l, mid);
build(x*2+1, mid+1, r);
pushup(x);
}
}
int query(int x, int l, int r)
{
if (tree[x].l>=l && tree[x].r<=r)
return tree[x].mmax;
else
{
int mid = (tree[x].l+tree[x].r)/2;
int ret = -1;
if (mid >= l)
ret = max(ret, query(x*2, l, r));
if (mid+1 <= r)
ret = max(ret, query(x*2+1, l, r));
return ret;
}
}
int main()
{
int N, M;
scanf("%d%d", &N, &M);
build(1, 1, N);
for (int i=1,x,y; i<=M; i++)
{
scanf("%d%d", &x, &y);
printf("%d\n",query(1, x, y));
}
return 0;
}
三分(凸函数)
#include <bits/stdc++.h>
const double eps = 1e-7;
using namespace std;
int N; double l, r;
double a[20];
double f(double x)
{
double ret = 0;
double tempx = 1;
for(int i=N+1; i>=1; i--)
{
ret += tempx*a[i];
tempx *= x;
}
return ret;
}
double triSection(double l, double r)
{
while (r-l > eps)
{
double mid1 = (l*2+r)/3;
double mid2 = (l+r*2)/3;
if (f(mid1) < f(mid2))
l = mid1;
else
r = mid2;
}
return l;
}
int main()
{
scanf("%d%lf%lf", &N, &l, &r);
for(int i=1; i<=N+1; i++)
scanf("%lf", a+i);
printf("%.5f\n", triSection(l,r));
return 0;
}
快速幂
LL quickPow(LL a, LL b)
{
LL ans = 1, base = a;
while (b != 0)
{
if ((b&1) != 0)
ans = (ans*base) % mod;
base = (base*base) % mod;
b >>= 1;
}
return ans;
}
矩阵快速幂
#include <bits/stdc++.h>
typedef long long LL;
const int maxn = 100;
const LL mod = 1000000007;
using namespace std;
int n; LL k;
struct tMatrix
{
LL mat[maxn+10][maxn+10];
tMatrix()
{
memset(mat, 0, sizeof(mat));
}
void build()
{
for (int i=1; i<=n; i++)
mat[i][i] = 1;
}
};
tMatrix operator*(const tMatrix& a, const tMatrix& b)
{
tMatrix c;
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
{
c.mat[i][j] = (c.mat[i][j]+a.mat[i][k]*b.mat[k][j]%mod)%mod;
}
return c;
}
tMatrix quickPowMat(tMatrix a, LL b)
{
tMatrix ans; ans.build();
tMatrix base = a;
while (b != 0)
{
if ((b&1) != 0)
ans = ans * base;
base = base * base;
b >>= 1;
}
return ans;
}
int main()
{
scanf("%d%lld", &n, &k);
tMatrix a;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
{
scanf("%lld", &a.mat[i][j]);
}
tMatrix ans = quickPowMat(a, k);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
{
printf("%lld", ans.mat[i][j]);
if (j == n)
printf("\n");
else
printf(" ");
}
return 0;
}
KMP
#include <bits/stdc++.h>
const int maxn = 1000000;
using namespace std;
char a[maxn+10], b[maxn+10];
int la, lb;
int nxt[maxn+10];
void getNext()
{
for (int i=2, j=0; i<=lb; i++)
{
while (j && b[j+1]!=b[i])
j = nxt[j];
if (b[j+1] == b[i])
j++;
nxt[i] = j;
}
}
void KMP()
{
//j means b[1..j] are successfully matched
for (int i=1, j=0; i<=la; i++)
{
while (j && b[j+1]!=a[i])
j = nxt[j];
if (b[j+1] == a[i])
j++;
if (j == lb)
{
printf("%d\n", i-lb+1);
j = nxt[j];
}
}
}
int main()
{
scanf("%s%s", a+1, b+1);
la = strlen(a+1);
lb = strlen(b+1);
getNext();
KMP();
for (int i=1; i<=lb; i++)
{
if (i==lb)
printf("%d\n", nxt[i]);
else
printf("%d ", nxt[i]);
}
return 0;
}
求逆元
模为素数
若\(p\)为素数,\(a\)为正整数,且\(a\)、\(p\)互质。则有\(a^{p-1}\equiv 1(mod\ p)\)。
quickPow(a, p-2);
模不为素数
void exGCD(LL a, LL b, LL &x, LL &y)
{
if (!b) x = 1, y = 0;
else
{
exGCD(b, a%b, y, x);
y -= a/b*x;
}
}
求一段逆元
#include <bits/stdc++.h>
typedef long long LL;
const int maxn = 20001000;
using namespace std;
LL inv[maxn+10];
int main()
{
LL n, p;
scanf("%lld%lld", &n, &p);
inv[1] = 1;
for (int i=2; i<=n; ++i)
inv[i] = (p - p / i) * inv[p % i] % p;
for (int i=1; i<=n; ++i)
printf("%lld\n", inv[i]);
return 0;
}
LCA
tarjan离线算法
#include <bits/stdc++.h>
const int maxn = 500000;
const int maxm = 500000;
using namespace std;
int to1[maxn*2+10];
int nxt1[maxn*2+10];
int head1[maxn+10], cnt1 = 0;
void addEdge(int x, int y)
{
to1[cnt1] = y; nxt1[cnt1] = head1[x];
head1[x] = cnt1++;
to1[cnt1] = x; nxt1[cnt1] = head1[y];
head1[y] = cnt1++;
}
int to2[maxm*2+10];
int w2[maxm*2+10];
int nxt2[maxm*2+10];
int head2[maxm+10], cnt2 = 0;
void addQuery(int a, int b)
{
to2[cnt2] = b; nxt2[cnt2] = head2[a];
head2[a] = cnt2++;
to2[cnt2] = a; nxt2[cnt2] = head2[b];
head2[b] = cnt2++;
}
int fa[maxn+10];
int vis[maxn+10];
int getFa(int x)
{
if (fa[x] == x)
return x;
return fa[x] = getFa(fa[x]);
}
void LCA(int x, int pre)
{
for (int i=head1[x]; i!=-1; i=nxt1[i])
{
int l = to1[i];
if (l != pre)
LCA(l, x);
}
//visit the root last
for (int i=head2[x]; i!=-1; i=nxt2[i])
{
int l = to2[i];
if (vis[l])
w2[i] = getFa(l);
}
fa[x] = pre;
vis[x] = 1;
}
int main()
{
int N, M, S;
scanf("%d%d%d", &N, &M, &S);
memset(head1, -1, sizeof(head1));
for (int i=1,x,y; i<=N-1; i++)
{
scanf("%d%d", &x, &y);
addEdge(x, y);
}
memset(w2, -1, sizeof(w2));
memset(head2, -1, sizeof(head2));
for (int i=1,a,b; i<=M; i++)
{
scanf("%d%d", &a, &b);
addQuery(a, b);
}
for (int i=1; i<=N; i++)
fa[i] = i;
memset(vis, 0, sizeof(vis));
LCA(S, S);
for (int i=0; i<=cnt2-1; i++)
{
if (w2[i] != -1)
printf("%d\n", w2[i]);
}
return 0;
}
FFT
#include <bits/stdc++.h>
const int maxn = 10000000;
const double PI = acos(-1.0);
using namespace std;
struct tComplex
{
double x, y;
tComplex(double xx = 0, double yy = 0)
{
x = xx; y = yy;
}
};
tComplex a[maxn+10];
tComplex b[maxn+10];
tComplex operator + (tComplex a, tComplex b)
{
return tComplex(a.x + b.x, a.y + b.y);
}
tComplex operator - (tComplex a, tComplex b)
{
return tComplex(a.x - b.x, a.y - b.y);
}
tComplex operator * (tComplex a, tComplex b)
{
return tComplex(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}
int l, r[maxn+10];
int limit = 1;
void FFT(tComplex A[], int type)
{
for (int i = 0; i < limit; i++)
{
if (i < r[i])
swap(A[i], A[r[i]]);
}
for (int mid = 1; mid < limit; mid <<= 1)
{
tComplex Wn(cos(PI/mid), type * sin(PI/mid));
for (int R = mid << 1, j = 0; j < limit; j += R)
{
tComplex w(1, 0);
for (int k = 0; k < mid; k++, w = w * Wn)
{
tComplex x = A[j+k], y = w * A[j+mid+k];
A[j+k] = x + y;
A[j+mid+k] = x - y;
}
}
}
}
int main()
{
int N, M;
scanf("%d%d", &N, &M);
for (int i = 0; i <= N; i++)
scanf("%lf", &a[i].x);
for (int i = 0; i <= M; i++)
scanf("%lf", &b[i].x);
while (limit <= N+M)
limit <<= 1, l++;
// get reverse order 0..limit-1
for (int i = 0; i < limit; i++)
r[i] = (r[i>>1]>>1) | ((i&1)<<(l-1));
FFT(a, 1);
FFT(b, 1);
for (int i = 0; i < limit; i++)
a[i] = a[i] * b[i];
FFT(a, -1);
for (int i = 0; i <= N+M; i++)
printf("%d ", (int)(a[i].x / limit + 0.5));
return 0;
}
Java大数
import java.math.BigInteger;
Scanner in = new Scanner(System.in);
BigInteger x1 = new BigInteger("-11"); //新建一个对象
BigInteger x2 = in.nextBiginteger();//键盘输入
BigInteger y = x1.abs(); //取绝对值
BigInteger y2 = x1.add(y); //x+y
int x3 = y.compareTo(x1); //x和y比较 < == >分别返回 -1,0,1
Boolean x4 = (y.compareTo(x1) <= 0); //判断y是否<=x 0是固定不变的,<=符号可以随意变
BigInteger x5 = y.divide(x1); // y/x1
BigInteger x6 = y.multiply(x1);// y*x1
double x6 = x2.doubleValue(); //将x2转化为double类型,转化为int用intValue()
BigInteger x7 = x2.gcd(x1);// 返回abs(x2)和abs(x1)的最大公约数
BigInteger x8 = x2.negate();// 返回-x2
String x9 = x2.toString();// 将x2转化为字符串
BigInteger y3 = x2.reamainder(x1);// 返回x2%x1
BigInteger y4= x1.pow(2);// pow(int exponent) 返回其值为 (this^exponent) 的 BigInteger。
去重离散化
浮点数
double a[maxn+5];//原数组1..n
int b[maxn+5];//离散后数组1..n
struct tdisc
{
double x;
int y;
bool operator<(const tdisc& rhs) const
{
return x<rhs.x;
}
};
tdisc disc[maxn+5];//排序用结构体1..n
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)//编号1..n
{
scanf("%lf",a+i);
disc[i]=(tdisc){a[i],i};
}
sort(disc+1,disc+1+n);
b[disc[1].y]=1;
for(int i=2,temp=1;i<=n;i++)
{
if(fabs(disc[i].x-disc[i-1].x)>eps)
temp++;
b[disc[i].y]=temp;
}
return 0;
}
整数
int a[maxn+5];//原数组1..n
int b[maxn+5];//离散后数组1..n
struct tdisc
{
int x;
int y;
bool operator<(const tdisc& rhs) const
{
return x < rhs.x;
}
};
tdisc disc[maxn+5];//排序用结构体1..n
int main()
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)//编号1..n
{
scanf("%d", a+i);
disc[i] = (tdisc){a[i], i};
}
sort(disc+1, disc+1+n);
b[disc[1].y] = 1;
for(int i=2, temp=1; i<=n; i++)
{
if(disc[i].x > disc[i-1].x)
temp++;
b[disc[i].y] = temp;
}
for(int i=1; i<=n; i++)
printf("%d ", b[i]);
return 0;
}
Cantor展开
//s[0..n-1]中存有n个不同的数,返回值从1开始的序号
int fac[] = {1,1,2,6,24,120,720,5040,40320,362880};
int cantor(int s[],int n)
{
int sum = 0;
for(int i = 0; i<n; i++)
{
int num = 0;
for(int j=i+1; j<n; j++)
if(s[j] < s[i])
num++;
sum += (num * fac[n-i-1]);
}
return sum + 1;
}
spfa, \(O(kE)/O(VE)\)
//链式前向星
int to[maxm*2+10];//maxm指边最大的数目
int w[maxm*2+10];
int nex[maxm*2+10];
int head[maxn+10], cnt;
int dis[maxn+10];//maxn为点最大的数目
int vis[maxn+10];
queue<int> q; q.push(s);//s为源点
for(int i=1; i<=n; i++)
dis[i] = inf;
dis[s] = 0; vis[s] = 1;
while(!q.empty())
{
int p = q.front(); q.pop();
vis[p] = 0;
for(int i = head[p]; i != -1; i = nex[i])
{
int l = to[i];
if(dis[l] > dis[p] + w[i])
{
dis[l] = dis[p] + w[i];
if(!vis[l])
{
vis[l] = 1;
q.push(l);
}
}
}
}
dijkstra
一般实现,\(O(V^2)\)
int dis[maxn+10];
int done[maxn+10];
memset(done, 0, sizeof(done));
for(int i=1; i<=n; i++)
dis[i] = inf;
dis[s] = 0;//s为源点
for(int i=1; i<=n; i++)
{
int x, m = inf;
for(int y=1; y<=n; y++)
{
if(!done[y] && dis[y]<=m)
m = d[x=y];
}
done[x] = 1;
for(int i = head[x]; i != -1; i = nex[i])
{
int l = to[i];
dis[l] = min(dis[l], dis[x]+w[i]);
}
}
堆优化实现,\(O(ElogV)\)
struct tnode
{
int d,u;//估计的距离,点的编号
bool operator < (const tnode& rhs) const
{
return d > rhs.d;
}
};
int dis[maxn+10];//距离
int done[maxn+10];//距离是否已确定
int s = 1;//s为源点
for(int i=1; i<=n; i++)
dis[i] = inf;
dis[s] = 0;
memset(done, 0, sizeof(done));
priority_queue<tnode> q;
q.push((tnode){0, s});
while(!q.empty())
{
tnode x = q.top(); q.pop();
int u = x.u;
if(done[u])
continue;
done[u] = 1;
for(int i=head[u]; i!=-1; i=nex[i])
{
int l = to[i];
if(dis[l] > dis[u]+w[i])
{
dis[l] = dis[u]+w[i];
q.push((tnode){dis[l], l});
}
}
}
带权并查集
struct tnode
{
int par;
int rel;//关系
};
tnode node[maxn+10];
int parent(int x)
{
if(node[x].par != x)
{
int temp = node[x].par;
node[x].par = parent(node[x].par);
node[x].rel = (node[x].rel+node[temp].rel) % 3;
}
return node[x].par;
}
bool unite(int d,int x,int y)
{
int px=parent(x), py=parent(y);
//rel和:px->py应该相当于px->x->y->pyrel
if(px!=py)
{
int temp=-node[x].rel+node[y].rel;
if(d == 2)
temp += 1;
temp = (temp%3+3)%3;//(-1)%3!=2而=-1
node[px].par = py;
node[px].rel = temp;
return true;
}
else
{
int temp = -node[x].rel+node[y].rel;
if(d == 2)
temp += 1;
temp = (temp%3+3)%3;
if(temp != 0)
return false;
return true;
}
}
尾声
也许还能用到吧,以后的学习。
算法竞赛,就此终了。
算法的学习,更广阔的学习,我仍在路上!