线性基
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
const int M = 1e4+10;
int a[M];
struct L_B{
int b[33],nb[33],tot;
void init(){
memset(b,0,sizeof(b));
}
bool Insert(int x){
for(int i = 30;i >= 0;i --){
if(x&(1<<i)){
if(!b[i]){
b[i] = x;
break;
}
x ^= b[i];
}
}
return x > 0;
}
int Max(int x){
int ret = x;
for(int i = 30;i >= 0;i --)
ret = max(ret,ret^b[i]);
return ret;
}
int Min(int x){
int ret = x;
for(int i = 0;i <= 30;i ++)
if(b[i]) ret ^= b[i];
return ret;
}
void rebuild(){
for(int i = 30;i >= 0;i --)
for(int j = i-1;j >= 0;j --)
if(b[i]&(1<<j)) b[i]^=b[j];
for(int i = 0;i <= 30;i ++)
if(b[i]) nb[tot++] = b[i];
}
int K_Min(int k){
int res = 0;
if(k >= (1<<tot))
return -1;
for(int i = 30;i >= 0;i --)
if(k&(1<<i))
res ^= nb[i];
return res;
}
L_B merge(L_B v){
L_B ret;
for(int i = 0;i <= 30;i ++) ret.b[i] = b[i];
for(int i = 0;i <= 30;i ++){
for(int j = i;j >= 0;j --){
if(v.b[i]&(1<<j)){
if(ret.b[j]) v.b[i] ^= ret.b[j];
else {
ret.b[j] = v.b[i]; break;
}
}
}
}
return ret;
}
}t[M<<2];
void build(int l,int r,int rt){
if(l == r){
t[rt].init();
t[rt].Insert(a[l]);
return ;
}
mid;
build(lson); build(rson);
t[rt] = t[rt<<1].merge(t[rt<<1|1]);
}
L_B query(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return t[rt];
}
mid;
if(L <= m&&m < R) return query(L,R,lson).merge(query(L,R,rson));
if(L <= m) return query(L,R,lson);
if(R > m) return query(L,R,rson);
}
int main()
{
int T,n,q,k,l,r;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&q,&k);
k = ~k;
for(int i = 1;i <= n;i ++)
scanf("%d",&a[i]),a[i]&=k;
k = ~k;
build(1,n,1);
for(int i = 1;i <= q;i ++){
scanf("%d%d",&l,&r);
L_B ans = query(l,r,1,n,1);
int an = ans.Max(k);
printf("%d
",an);
}
}
return 0;
}
三维偏序
#include<bits/stdc++.h>
#define _ 100001
#define mid ((l+r)>>1)
using namespace std;
struct ee{
int x,y,z,siz,ans;
}e[_*2],b[_];
int n,k,tr[_*21+1],ot[_*2],w;
long long A=0;
bool cp1(ee a,ee bo){
if(a.x!=bo.x)
return a.x<bo.x;
if(a.y!=bo.y)
return a.y<bo.y;
return a.z<bo.z;
}
bool cp2(ee a,ee bo){
if(a.y!=bo.y)//OMG NO"X"!!!
return a.y<bo.y;
return a.z<bo.z;
}
int lbt(int x){return x&-x;}
void add(int x,int ad){
while(x<=k){
tr[x]+=ad;
x+=lbt(x);
}
}
int query(int x){
int r=0;
while(x){
r+=tr[x];
x-=lbt(x);
}return r;
}
void cdQ(int l,int r){
if(l==r)return;
cdQ(l,mid);
cdQ(mid+1,r);
sort(b+l,b+mid+1,cp2);
sort(b+mid+1,b+r+1,cp2);
int i=mid+1,j=l;
for(;i<=r;i++){
while(b[j].y<=b[i].y&&j<=mid)
add(b[j].z,b[j].siz),j++;
A+=query(b[i].z);
}
for(int i=l;i<j;i++)
add(b[i].z,-b[i].siz);
}
int main(){
cin>>n;k=n;
for(int i=1;i<=3;i++){
for(int j=1,xx;j<=n;j++){
scanf("%d",&xx);
if(i==1) e[xx].x=j;
if(i==2) e[xx].y=j;
if(i==3) e[xx].z=j;
}
}
sort(e+1,e+1+n,cp1);
w=0;
for(int i=1;i<=n;i++){
if(e[i].x!=e[i-1].x||e[i].y!=e[i-1].y||e[i].z!=e[i-1].z){++w;b[w]=e[i];}
b[w].siz++;
}
cdQ(1,w);
// for(int i=1;i<=w;i++)
// ot[b[i].ans+b[i].siz-1]+=b[i].siz;
// for(int i=0;i<n;i++)
printf("%lld
",A);return 0;
}
树上莫队
/*
* @Author: zhl
* @Date: 2020-11-19 15:34:09
*/
#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define pb(x) push_back(x)
using namespace std;
const int N = 1e5 + 10;
vector<int>G[N];
int n, m, len, ID[N], ans[N];
int w[N], nums[N], in[N], out[N], ord[N];
int tot, dep[N], f[N][32], cnt[N], st[N];
void add(int x, int& res) {
st[x] ^= 1;
if (!st[x]) {
if (!--cnt[w[x]])res--;
}
else {
if (!cnt[w[x]]++)res++;
}
}
void dfs(int u, int p) {
in[u] = ++tot;
ord[tot] = u;
dep[u] = dep[p] + 1; f[u][0] = p;
for (int x = 1; (1 << x) < dep[u]; x++) {
f[u][x] = f[f[u][x - 1]][x - 1];
}
for (int v : G[u]) {
if (v == p)continue;
dfs(v, u);
}
out[u] = ++tot;
ord[tot] = u;
}
int LCA(int x, int y) {
if (dep[x] < dep[y])swap(x, y);
while (dep[x] != dep[y]) {
int u = dep[x] - dep[y];
int v = 0;
while (!(u & (1 << v)))v++;
x = f[x][v];
}
while (x != y) {
int v = 0;
while (f[x][v] != f[y][v])v++;
x = f[x][max(0, v - 1)]; y = f[y][max(0, v - 1)];
}
return x;
}
struct Query {
int id, l, r, lca;
bool operator < (const Query& b)const {
if (ID[l] != ID[b.l])return ID[l] < ID[b.l];
return r < b.r;
}
}q[N];
int main() {
scanf("%d%d", &n, &m); int numID = 0;
for (int i = 1; i <= n; i++)scanf("%d", w + i), nums[++numID] = w[i];
sort(nums + 1, nums + 1 + n);
numID = unique(nums + 1, nums + 1 + n) - nums - 1;
for (int i = 1; i <= n; i++)w[i] = lower_bound(nums + 1, nums + 1 + numID, w[i]) - nums;
for (int i = 1; i < n; i++) {
int a, b; scanf("%d%d", &a, &b);
G[a].pb(b); G[b].pb(a);
}
dfs(1, 0);
len = sqrt(tot);
for (int i = 1; i <= tot; i++)ID[i] = i / len;
for (int i = 1; i <= m; i++) {
int x, y; scanf("%d%d", &x, &y);
int lca = LCA(x, y);
if (in[x] > in[y])swap(x, y);
if (lca == x) {
q[i] = { i,in[x],in[y],0 };
}
else {
q[i] = { i,out[x],in[y],lca };
}
}
sort(q + 1, q + 1 + m);
int res = 0, l = 1, r = 0;
for (int i = 1; i <= m; i++) {
int ql = q[i].l, qr = q[i].r, lca = q[i].lca;
if (lca != 0)add(lca, res);
while (l < ql)add(ord[l++], res);
while (l > ql)add(ord[--l], res);
while (r < qr)add(ord[++r], res);
while (r > qr)add(ord[r--], res);
ans[q[i].id] = res;
if (lca != 0)add(lca, res);
}
for (int i = 1; i <= m; i++)printf("%d
", ans[i]);
}
dsu on tree
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN = 1e5 + 10;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, col[MAXN], son[MAXN], siz[MAXN], cnt[MAXN], Mx, Son;
LL sum = 0, ans[MAXN];
vector<int> v[MAXN];
void dfs(int x, int fa) {
siz[x] = 1;
for(int i = 0; i < v[x].size(); i++) {
int to = v[x][i];
if(to == fa) continue;
dfs(to, x);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;//轻重链剖分
}
}
void add(int x, int fa, int val) {
cnt[col[x]] += val;//这里可能会因题目而异
if(cnt[col[x]] > Mx) Mx = cnt[col[x]], sum = col[x];
else if(cnt[col[x]] == Mx) sum += (LL)col[x];
for(int i = 0; i < v[x].size(); i++) {
int to = v[x][i];
if(to == fa || to == Son) continue;
add(to, x, val);
}
}
void dfs2(int x, int fa, int opt) {
for(int i = 0; i < v[x].size(); i++) {
int to = v[x][i];
if(to == fa) continue;
if(to != son[x]) dfs2(to, x, 0);//暴力统计轻边的贡献,opt = 0表示递归完成后消除对该点的影响
}
if(son[x]) dfs2(son[x], x, 1), Son = son[x];//统计重儿子的贡献,不消除影响
add(x, fa, 1); Son = 0;//暴力统计所有轻儿子的贡献
ans[x] = sum;//更新答案
if(!opt) add(x, fa, -1), sum = 0, Mx = 0;//如果需要删除贡献的话就删掉
}
int main() {
N = read();
for(int i = 1; i <= N; i++) col[i] = read();
for(int i = 1; i <= N - 1; i++) {
int x = read(), y = read();
v[x].push_back(y); v[y].push_back(x);
}
dfs(1, 0);
dfs2(1, 0, 0);
for(int i = 1; i <= N; i++) printf("%I64d ", ans[i]);
return 0;
}
CDQ
#include<bits/stdc++.h>
#define _ 100001
#define mid ((l+r)>>1)
#define re(x) scanf("%d",&x)
using namespace std;
struct ee{
int x,y,z,siz,ans;
}e[_],b[_];
int n,k,tr[_*21+1],ot[_*2],w;
bool cp1(ee a,ee bo){
if(a.x!=bo.x)
return a.x<bo.x;
if(a.y!=bo.y)
return a.y<bo.y;
return a.z<bo.z;
}
bool cp2(ee a,ee bo){
if(a.y!=bo.y)//OMG NO"X"!!!
return a.y<bo.y;
return a.z<bo.z;
}
int lbt(int x){return x&-x;}
void add(int x,int ad){
while(x<=k){
tr[x]+=ad;
x+=lbt(x);
}
}
int query(int x){
int r=0;
while(x){
r+=tr[x];
x-=lbt(x);
}return r;
}
void cdQ(int l,int r){
if(l==r)return;
cdQ(l,mid);
cdQ(mid+1,r);
sort(b+l,b+mid+1,cp2);
sort(b+mid+1,b+r+1,cp2);
int i=mid+1,j=l;
for(;i<=r;i++){
while(b[j].y<=b[i].y&&j<=mid)
add(b[j].z,b[j].siz),j++;
b[i].ans+=query(b[i].z);
}
for(int i=l;i<j;i++)
add(b[i].z,-b[i].siz);
}
int main(){
re(n);re(k);
for(int i=1;i<=n;i++)
re(e[i].x),re(e[i].y),re(e[i].z);
sort(e+1,e+1+n,cp1);
w=0;
for(int i=1;i<=n;i++){
if(e[i].x!=e[i-1].x||e[i].y!=e[i-1].y||e[i].z!=e[i-1].z){++w;b[w]=e[i];}
b[w].siz++;
// cout<<w<<":"<<b[w].siz<<endl;
}
cdQ(1,w);
for(int i=1;i<=w;i++)
ot[b[i].ans+b[i].siz-1]+=b[i].siz;
for(int i=0;i<n;i++)
printf("%d
",ot[i]);return 0;
}
计算几何
求圆交:
const db pi=acos(-1);
db r1,r2,d,len;
struct Point{db x,y;}a,b;
inline db sqr(db x){return x*x;}
inline db dis(Point a,Point b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
db solve()
{
db d=dis(a,b);
if(d>=r1+r2) return 0.0;
if(d<=r1-r2) return pi*r2*r2;
if(d<=r2-r1) return pi*r1*r1;
db p=(r1+r2+d)/2.0;
db a1=acos((r1*r1+d*d-r2*r2)/(2.0*r1*d));
db a2=acos((r2*r2+d*d-r1*r1)/(2.0*r2*d));
return a1*r1*r1+a2*r2*r2-2.0*sqrt(p*(p-r1)*(p-r2)*(p-d));
}
int main()
{
rep(T,1,read())
{
cin>>r1>>a.x>>a.y>>r2>>b.x>>b.y>>len;
if(len*len>=r2*r2*2) {puts("0.000000");continue;}
r1=sqrt(sqr(r1)-sqr(len/2))-len/2;
r2=sqrt(sqr(r2)-sqr(len/2))-len/2;
printf("%.6lf
",solve()/(pi*r1*r1));
}
}
线段树优化建边
#include <bits/stdc++.h>
using namespace std;
#define File(x) freopen("(x)","r",stdin)
#define pf printf
#define ull unsigned long long
#define db double
#define ll long long
#define MAXN 100005
#define MAXM
#define P
#define lson (u<<1)
#define rson (u<<1|1)
const ll inf=1e16;
int n,q,s,cnt;
int id1[MAXN<<2],id2[MAXN<<2];
vector<int>v1[MAXN*9],v2[MAXN*9];
ll dis[MAXN<<3];
bool In[MAXN<<3];
void add(int u,int v,int val){
v1[u].push_back(v);
v2[u].push_back(val);
}
void build1(int u,int l,int r){
int mid=l+r>>1;
id1[u]=++cnt;
if(l==r){
id1[u]=l;
return;
}
build1(u<<1,l,mid);
build1(u<<1|1,mid+1,r);
add(id1[u],id1[lson],0);
add(id1[u],id1[rson],0);
}
void build2(int u,int l,int r){
int mid=l+r>>1;
id2[u]=++cnt;
if(l==r){
id2[u]=l;
return;
}
build2(u<<1,l,mid);
build2(u<<1|1,mid+1,r);
add(id2[lson],id2[u],0);
add(id2[rson],id2[u],0);
}
void upd(int u,int L,int R,int v,int l,int r,int w,int op){
if(L>=l&&R<=r){
if(op==2)add(v,id1[u],w);
else add(id2[u],v,w);
return;
}
int mid=L+R>>1;
if(l<=mid)upd(lson,L,mid,v,l,r,w,op);
if(r>mid)upd(rson,mid+1,R,v,l,r,w,op);
}
void DJ(){
for(int i=1;i<=cnt;i++)dis[i]=inf;
priority_queue<pair<ll,int>>q;
dis[s] = 0;
q.push(make_pair(0,s));
while(!q.empty()){
int x = q.top().second;
q.pop();
if(In[x])continue;
In[x] = 1;
for(int i = 0; i<v1[x].size();i ++){
int y = v1[x][i];
ll z = v2[x][i];
if(dis[y] > dis[x] + z){
dis[y] = dis[x] + z;
q.push(make_pair(-dis[y], y));
}
}
}
}
int main(){
cin>>n>>q>>s;
cnt=n;
build1(1,1,n);
build2(1,1,n);
while(q--){
int op,v,u,w,l,r;
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&v,&u,&w);
add(v,u,w);
}
else{
scanf("%d%d%d%d",&v,&l,&r,&w);
upd(1,1,n,v,l,r,w,op);
}
}
DJ();
for(int i=1;i<=n;i++){
if(dis[i]==inf)printf("-1 ");
else printf("%lld ",dis[i]);
}
return 0;
}
后缀自动机
#include<bits/stdc++.h>
#define N shus2000005
typedef long long ll;
using namespace std;
char s[N];
int a[N],c[N],size[N],n;
ll ans=0;
struct SuffixAutoMaton{
int last,cnt;int ch[N<<1][26],fa[N<<1],l[N<<1];
void ins(int c){
int p=last,np=++cnt;last=np;l[np]=l[p]+1;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
if(!p)fa[np]=1;
else{
int q=ch[p][c];
if(l[p]+1==l[q])fa[np]=q;
else{
int nq=++cnt;l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
}
}
size[np]=1;
}
void build(){
scanf("%s",s+1);int len=strlen(s+1);
last=cnt=1;for(int i=1;i<=len;i++)ins(s[i]-'a');
}
void calc(){
for(int i=1;i<=cnt;i++)c[l[i]]++;
for(int i=1;i<=cnt;i++)c[i]+=c[i-1];
for(int i=1;i<=cnt;i++)a[c[l[i]]--]=i;//a
for(int i=cnt;i;i--){
int p=a[i];
size[fa[p]]+=size[p];
if(size[p]>1)ans=max(ans,1LL*size[p]*l[p]);
}
printf("%lld
",ans);
}
}sam;
int main(){
sam.build();
sam.calc();
}
后缀数组
#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int t1[N],t2[N],sa[N],h[N],rk[N],c[10*N],a[N];
char s[N];
int m,n;
void calcsa(int n,int m){
int *x=t1,*y=t2,p=0,f=0;
for(int i=1;i<=m;i++)c[i]=0;
for(int i=1;i<=n;i++)c[x[i]=a[i]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int i=n;i;i--)sa[c[x[i]]--]=i;
for(int i=1;i<=n&&p<=n;i<<=1){
p=0;
for(int j=n-i+1;j<=n;j++)y[++p]=j;
for(int j=1;j<=n;j++)if(sa[j]>i)y[++p]=sa[j]-i;
for(int j=1;j<=m;j++)c[j]=0;
for(int j=1;j<=n;j++)c[x[y[j]]]++;
for(int i=1;i<=m;i++)c[i]+=c[i-1];
for(int j=n;j;j--)sa[c[x[y[j]]]--]=y[j];
swap(x,y);x[sa[1]]=1;p=2;
for(int j=2;j<=n;j++)
x[sa[j]]=y[sa[j]]==y[sa[j-1]]&&y[sa[j]+i]==y[sa[j-1]+i]?p-1:p++;
m=p;
}
for(int i=1;i<=n;i++)rk[sa[i]]=i;
for(int i=1;i<=n;i++){
int j=sa[rk[i]-1];
if(f)f--;while(a[i+f]==a[j+f])f++;
h[rk[i]]=f;
}
}
int main(){
scanf("%s",s);int len=strlen(s);
for(int i=0;i<len;i++)a[++n]=s[i]-' ';
calcsa(n,10000);
for(int i=1;i<=n;i++)printf("%d ",sa[i]);
return 0;
}
斜率优化DP
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define _ 50001
#define db double
#define re(x) scanf("%lld",&x);
using namespace std;
ll sum[_],N,L;
int Q[_],hd,tl;
db f[_];
db a(int i){return sum[i]+i-L-1;}
db b(int i){return sum[i]+i;}
db x(int i){return b(i);}
db y(int i){return f[i]+b(i)*b(i);}
db k(int i,int j){return (y(i)-y(j))/(x(i)-x(j));}
int main(){
re(N);re(L);
for(int i=1;i<=N;i++){
re(sum[i]);
sum[i]+=sum[i-1];
}
hd=tl=1;
for(int i=1;i<=N;i++){
while(hd<tl&&k(Q[hd],Q[hd+1])<2*a(i))++hd;
f[i]=f[Q[hd]]+(a(i)-b(Q[hd]))*(a(i)-b(Q[hd]));
while(hd<tl&&k(Q[tl],i)<k(Q[tl],Q[tl-1]))--tl;
Q[++tl]=i;
}printf("%lld
",(ll)f[N]);
}
KM
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
#define N 300 + 5
#define MXL 1234567890987654321LL
int n, X[N], Y[N], Z[N], V[N], P[N], F[N];
LL W[N][N], L[N], R[N], S[N];
bool Vis[N];
LL KM()
{
fill(P, P + n + 1, 0);
fill(R, R + n + 1, 0);
for (int i = 1; i <= n; i ++)
R[0] -= L[i] = *max_element(W[i] + 1, W[i] + n + 1);
for (int i = 1; i <= n; i ++)
{
fill(S, S + n + 1, MXL * 2);
fill(Vis, Vis + n + 1, false);
int y = 0, t;
P[0] = i;
do
{
Vis[y] = true;
int x = P[y];
LL d = MXL * 2;
for (int j = 1; j <= n; j ++)
if (!Vis[j])
{
LL c = L[x] + R[j] - W[x][j];
if (c < S[j])
S[j] = c, F[j] = y;
if (S[j] < d)
d = S[j], t = j;
}
if (W[P[F[t]]][t] == -MXL)
return -MXL;
for (int j = 0; j <= n; j ++)
{
if (Vis[j])
L[P[j]] -= d, R[j] += d;
else S[j] -= d;
}
} while (P[y = t]);
while (y) P[y] = P[F[y]], y = F[y];
}
return -R[0];
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++)
{
scanf("%d%d%d%d", X + i, Y + i, Z + i, V + i);
for (int j = 0; j < n; j ++)
W[i][j + 1] = -(X[i] * X[i] + Y[i] * Y[i] + 1LL * (Z[i] + j * V[i]) * (Z[i] + j * V[i]));
}
printf("%lld
", -KM());
return 0;
}
扫描线
#include<cstdio>
#include<algorithm>
#define ri register int
using namespace std;
typedef long long ll;
ll ans;
ll n;
ll x1,x2,y1,y2;
ll y[210000];
struct smx
{
ll y1,y2,x,mark;
}line[210000];
bool cmp(smx a,smx b){return a.x<b.x;}//排序
struct node
{
ll c,tag;
//tag用来判断扫描线扫到下一条线段时还包不包括这个矩形
}tr[810000];
void pushup(ll num,ll l,ll r)
{
if(!tr[num].tag)
{
if(l==r)tr[num].c=0;
else tr[num].c=tr[num<<1].c+tr[num<<1|1].c;
}
}
void change(ll num,ll l,ll r,ll y1,ll y2,ll k)//这里的l,r是num的管理范围,y1、y2是上一个代码的l,r
{
if(y1<=l&&r<=y2)
{
tr[num].tag+=k;
if(tr[num].tag)tr[num].c=y[r+1]-y[l];
else tr[num].c=0;
pushup(num,l,r);
return ;
}
ll mid=(l+r)>>1;
if(y1<=mid)change(num<<1,l,mid,y1,y2,k);
if(mid+1<=y2)change(num<<1|1,mid+1,r,y1,y2,k);
pushup(num,l,r);
}
int main()
{
scanf("%lld",&n);
for(ri i=1;i<=n;i++)
{
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
y[(i<<1)-1]=y1;y[i<<1]=y2;
line[(i<<1)-1]=(smx){y1,y2,x1,3};line[i<<1]=(smx){y1,y2,x2,-3};
}
n<<=1;
sort(y+1,y+n+1);
sort(line+1,line+n+1,cmp);
int len=unique(y+1,y+n+1)-(&y[1])-1;
for(ri i=1;i<n;i++)
{
y1=lower_bound(y+1,y+len+2,line[i].y1)-y;
y2=lower_bound(y+1,y+len+2,line[i].y2)-y-1;
change(1,1,len,y1,y2,line[i].mark);
ans+=tr[1].c*(line[i+1].x-line[i].x);
}
printf("%lld
",ans);
return 0;
}
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
const int maxn=20010;
struct tree {int l,r,len,ls,rs,num,cov;}tr[maxn<<2];
struct data {int x,l,r,val;}a[maxn];
int n;
void build(int k,int s,int t) {
tr[k].l=s;tr[k].r=t;
if (s==t) return;
int mid=(s+t)>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
}
void merge(int k) {
int l=tr[k].l,r=tr[k].r;
if (tr[k].cov) {
tr[k].ls=tr[k].rs=1;
tr[k].num=2;
tr[k].len=r-l+1;
}
else if (l==r) tr[k].ls=tr[k].rs=tr[k].len=tr[k].num=0;
else {
tr[k].num=tr[k<<1].num+tr[k<<1|1].num;
tr[k].len=tr[k<<1].len+tr[k<<1|1].len;
tr[k].ls=tr[k<<1].ls;tr[k].rs=tr[k<<1|1].rs;
if (tr[k<<1].rs && tr[k<<1|1].ls) tr[k].num-=2;
}
}
void update(int k,int s,int t,int val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (s<=l && t>=r) {tr[k].cov+=val;merge(k);return;}
if (s<=mid) update(k<<1,s,t,val);
if (t>mid) update(k<<1|1,s,t,val);
merge(k);
}
bool cmpx(data a,data b) {
return a.x<b.x;
}
int main() {
scanf("%d",&n);
int m=0,l=inf,r=-inf;
for (int x1,x2,y1,y2,i=1;i<=n;i++) {
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
l=min(l,y1);r=max(r,y2);
a[++m]=(data){x1,y1,y2,1};a[++m]=(data){x2,y1,y2,-1};
}
n=m;
build(1,l,r-1);
sort(a+1,a+1+n,cmpx);
int ans=0;
for (int i=1;i<=n;i++) {
int tmp=tr[1].len;
if (i!=1) ans+=tr[1].num*(a[i].x-a[i-1].x);
update(1,a[i].l,a[i].r-1,a[i].val);
ans+=abs(tr[1].len-tmp);
}
printf("%d",ans);
return 0;
}
SA
#include <bits/stdc++.h>
using namespace std;
const int maxn = 300 + 5;
long long gb, cb;
long long int x[maxn], y[maxn], z[maxn], v[maxn], seq[maxn];
double eps = 1e-6;
int n, rand_k1, rand_k2;
void SA()
{
srand(time(NULL));
for (double T = 100000000; T > eps; T *= 0.96)
{
int time = 10000;
while (time--)
{
rand_k1 = rand() % n, rand_k2 = rand() % n;
long long nxtval = cb - (z[seq[rand_k1]] + rand_k1 * v[seq[rand_k1]]) * (z[seq[rand_k1]] + rand_k1 * v[seq[rand_k1]])
- (z[seq[rand_k2]] + rand_k2 * v[seq[rand_k2]]) * (z[seq[rand_k2]] + rand_k2 * v[seq[rand_k2]]);
swap(seq[rand_k1], seq[rand_k2]);
nxtval+= (z[seq[rand_k1]] + rand_k1 * v[seq[rand_k1]]) * (z[seq[rand_k1]] + rand_k1 * v[seq[rand_k1]])
+(z[seq[rand_k2]] + rand_k2 * v[seq[rand_k2]]) * (z[seq[rand_k2]] + rand_k2 * v[seq[rand_k2]]);
long long deltax = nxtval-cb;
if (deltax <= 0)
{
cb = nxtval;
gb = min(gb, cb);
}
else
{
if (exp(-1*deltax / T) > (long double)rand() / RAND_MAX)
{
cb = nxtval;
}
else
{
swap(seq[rand_k1], seq[rand_k2]);
}
}
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
scanf("%lld%lld%lld%lld", &x[i], &y[i], &z[i], &v[i]);
}
for (int i = 0; i < n; i++)
{
seq[i] = i;
}
random_shuffle(seq, seq + n);
for (int i = 0; i < n; i++)
{
gb += x[seq[i]] * x[seq[i]] + y[seq[i]] * y[seq[i]] + (z[seq[i]] + i * v[seq[i]]) * (z[seq[i]] + i * v[seq[i]]);
}
cb = gb;
SA();
cout << gb << endl;
return 0;
}
FFT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const double PI=acos(-1.0);
struct complex
{
double l,r;
complex(double ll=0.0,double rr=0.0){
l=ll;r=rr;
}
complex operator +(const complex& B){
return complex(l+B.l,r+B.r);
}
complex operator - (const complex& B){
return complex(l-B.l,r-B.r);
}
complex operator *(const complex& B){
return complex(l*B.l-r*B.r,l*B.r+B.l*r);
}
};
/*
* 进行FFT和IFFT前的反转变换。
* 位置i和j(i二进制反转后位置)互换
* len必须是2的幂
*/
void change(complex y[],int len){
int i,j,k;
for (int i=1,j=len/2;i<len-1;i++){
if (i<j) swap(y[i],y[j]);
k=len/2;
while (j>=k){
j-=k;
k>>=1;
}
if (j<k) j+=k;
}
}
/*
* 做FFT
* len必须为2^k形式,
* on==1时是DFT,on==-1时是IDFT
*/
void fft(complex y[],int len,int on){
change(y,len);
for (int h=2;h<=len;h<<=1){
complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for (int j=0;j<len;j+=h){
complex w(1,0);
for (int k=j;k<j+h/2;k++){
complex u=y[k];
complex t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
}
}
}
if (on==-1){
for (int i=0;i<len;i++){
y[i].l/=len;
}
}
}
const int MAXN=200010;
complex x1[MAXN],x2[MAXN];
char s1[MAXN],s2[MAXN];
int sum[MAXN];
int main()
{
while (~scanf("%s%s",s1,s2)){
int len1=strlen(s1);
int len2=strlen(s2);
int len=1;
while (len<len1*2||len<len2*2) len<<=1;
for (int i=0;i<len1;i++){
x1[i]=complex(s1[len1-1-i]-'0',0);
}
for (int i=len1;i<len;i++){
x1[i]=complex(0,0);
}
for (int i=0;i<len2;i++){
x2[i]=complex(s2[len2-1-i]-'0',0);
}
for (int i=len2;i<len;i++) x2[i]=complex(0,0);
fft(x1,len,1);
fft(x2,len,1);
for (int i=0;i<len;i++){
x1[i]=x1[i]*x2[i];
}
fft(x1,len,-1);
//化简和进位
for (int i=0;i<len;i++){
sum[i]=(int) (x1[i].l+0.5);
}
for(int i=0;i<len;i++){
sum[i+1]+=(sum[i]/10);
sum[i]%=10;
}
len=len1+len2-1;
while (sum[len]<=0&&len>0) len--;
for (int i=len;i>=0;i--){
printf("%c",sum[i]+'0');
}
printf("
");
}
}
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN=1e7+10;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
const double Pi=acos(-1.0);
struct complex
{
double x,y;
complex (double xx=0,double yy=0){x=xx,y=yy;}
}a[MAXN],b[MAXN];
complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);}
complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);}
complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);}//不懂的看复数的运算那部分
int N,M;
int l,r[MAXN];
int limit=1;
void fast_fast_tle(complex *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)//待合并区间的中点
{
complex Wn( cos(Pi/mid) , type*sin(Pi/mid) ); //单位根
for(int R=mid<<1,j=0;j<limit;j+=R)//R是区间的右端点,j表示前已经到哪个位置了
{
complex w(1,0);//幂
for(int k=0;k<mid;k++,w=w*Wn)//枚举左半部分
{
complex 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=read(),M=read();
for(int i=0;i<=N;i++) a[i].x=read();
for(int i=0;i<=M;i++) b[i].x=read();
while(limit<=N+M) limit<<=1,l++;
for(int i=0;i<limit;i++)
r[i]= ( r[i>>1]>>1 )| ( (i&1)<<(l-1) ) ;
// 在原序列中 i 与 i/2 的关系是 : i可以看做是i/2的二进制上的每一位左移一位得来
// 那么在反转后的数组中就需要右移一位,同时特殊处理一下复数
fast_fast_tle(a,1);
fast_fast_tle(b,1);
for(int i=0;i<=limit;i++) a[i]=a[i]*b[i];
fast_fast_tle(a,-1);
for(int i=0;i<=N+M;i++)
printf("%d ",(int)(a[i].x/limit+0.5));
return 0;
}
fwt
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#include<map>
#include<vector>
#define int long long
using namespace std;
const int N=(1<<17|1);
const int mod=998244353;
int a[N],b[N];
int A[N],B[N];
int n;
int read()
{
int f=1,x=0;
char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+(s^'0');s=getchar();}
return f*x;
}
int quick(int x,int p)
{
int ret=1;
while(p)
{
if(p&1) ret=ret*x%mod;
x=x*x%mod;
p>>=1;
}
return ret;
}
void OR(int *f,int x)
{
for(int mid=1;(mid<<1)<=n;mid<<=1)
{
int R=mid<<1;
for(int i=0;i<n;i+=R)
for(int j=0;j<mid;j++)
f[i+j+mid]=(f[i+j+mid]+f[i+j]*x+mod)%mod;
}
}
void AND(int *f,int x)
{
for(int mid=1;(mid<<1)<=n;mid<<=1)
{
int R=mid<<1;
for(int i=0;i<n;i+=R)
for(int j=0;j<mid;j++)
f[i+j]=(f[i+j]+f[i+j+mid]*x+mod)%mod;
}
}
void XOR(int *f,int x)
{
for(int mid=1;(mid<<1)<=n;mid<<=1)
{
int R=mid<<1;
for(int i=0;i<n;i+=R)
for(int j=0;j<mid;j++)
{
f[i+j]=(f[i+j]+f[i+j+mid])%mod;
f[i+j+mid]=(f[i+j]-f[i+j+mid]+mod-f[i+j+mid]+mod)%mod;
f[i+j]=f[i+j]*x%mod;
f[i+j+mid]=f[i+j+mid]*x%mod;
}
}
}
void Copy()
{
for(int i=0;i<n;i++)
a[i]=A[i];
for(int i=0;i<n;i++)//
b[i]=B[i];
}
void Merge(int *a,int *b)
{
for(int i=0;i<n;i++)
a[i]=a[i]*b[i]%mod;
}
void Out()
{
for(int i=0;i<n;i++)
printf("%lld ",a[i]);
cout<<endl;
}
signed main()
{
int m=read();
n=(1<<m);
for(int i=0;i<n;i++)
A[i]=read();
for(int i=0;i<n;i++)
B[i]=read();
Copy(); OR(a,1); OR(b,1); Merge(a,b); OR(a,-1); Out();
Copy(); AND(a,1); AND(b,1); Merge(a,b); AND(a,-1); Out();
Copy(); XOR(a,1); XOR(b,1); Merge(a,b); XOR(a,quick(2ll,mod-2)); Out();
return 0;
}
点分治
#include<cstdio>
#include<algorithm>
#include<cstring>
#define F(i,a,b) for(int i=a;i<=(b);++i)
#define eF(i,u) for(int i=h[u];i;i=nxt[i])
using namespace std;
const int INF=0x3f3f3f3f;
int n,k,Ans;
int h[10001],nxt[20001],to[20001],w[20001],tot;
inline void ins(int x,int y,int z){nxt[++tot]=h[x];to[tot]=y;w[tot]=z;h[x]=tot;}
bool vis[10001];
int Root,Tsiz,siz[10001],wt[10001];
int arr[10001],cnt;
void GetRoot(int u,int f){
siz[u]=1; wt[u]=0;
eF(i,u) if(to[i]!=f&&!vis[to[i]])
GetRoot(to[i],u), siz[u]+=siz[to[i]], wt[u]=max(wt[u],siz[to[i]]);
wt[u]=max(wt[u],Tsiz-siz[u]);
if(wt[Root]>wt[u]) Root=u;
}
void Dfs(int u,int D,int f){
arr[++cnt]=D;
eF(i,u) if(to[i]!=f&&!vis[to[i]]) Dfs(to[i],D+w[i],u);
}
int calc(int u,int D){
cnt=0; Dfs(u,D,0); int l=1,r=cnt,sum=0;
sort(arr+1,arr+cnt+1);
for(;;++l){
while(r&&arr[l]+arr[r]>k) --r;
if(r<l) break;
sum+=r-l+1;
}
return sum;
}
void DFS(int u){
Ans+=calc(u,0); vis[u]=1;
eF(i,u) if(!vis[to[i]]){
Ans-=calc(to[i],w[i]);
Root=0, Tsiz=siz[to[i]], GetRoot(to[i],0);
DFS(Root);
}
}
int main(){
int x,y,z;
while(~scanf("%d%d",&n,&k)&&n&&k){
tot=Ans=0; memset(vis,0,sizeof vis); memset(h,0,sizeof h);
F(i,2,n) scanf("%d%d%d",&x,&y,&z), ins(x,y,z), ins(y,x,z);
wt[Root = 0]=INF; Tsiz=n; GetRoot(1,0);
DFS(Root);
printf("%d
",Ans-n);
}
return 0;
}
2-SAT
HDU 3622
/*
HDU 3622
题意:给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),
每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸
的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相
交(可以相切),求解这个最大半径.
首先二分最大半径值,然后2-sat构图判断其可行性,对于每
两队位置(u,uu)和(v,vv),如果u和v之间的距离小于2*id,也就
是说位置u和位置v处不能同时防止炸弹(两范围相交),所以连边(u,vv)
和(v,uu),求解强连通分量判断可行性.
注意精度问题
*/
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
using namespace std;
const int MAXN=210;
const int MAXM=40005;//边的最大数
const double eps=1e-5;
struct Edge
{
int to,next;
}edge1[MAXM],edge2[MAXM];
int head1[MAXN];
int head2[MAXN];
int tol1,tol2;
bool vis1[MAXN],vis2[MAXN];
int Belong[MAXN];//连通分量标记
int T[MAXN];//dfs结点结束时间
int Bcnt,Tcnt;
void add(int a,int b)//原图和逆图都要添加
{
edge1[tol1].to=b;
edge1[tol1].next=head1[a];
head1[a]=tol1++;
edge2[tol2].to=a;
edge2[tol2].next=head2[b];
head2[b]=tol2++;
}
void init()//建图前初始化
{
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(vis1,false,sizeof(vis1));
memset(vis2,false,sizeof(vis2));
tol1=tol2=0;
Bcnt=Tcnt=0;
}
void dfs1(int x)//对原图进行dfs,算出每个结点的结束时间,哪个点开始无所谓
{
vis1[x]=true;
int j;
for(int j=head1[x];j!=-1;j=edge1[j].next)
if(!vis1[edge1[j].to])
dfs1(edge1[j].to);
T[Tcnt++]=x;
}
void dfs2(int x)
{
vis2[x]=true;
Belong[x]=Bcnt;
int j;
for(j=head2[x];j!=-1;j=edge2[j].next)
if(!vis2[edge2[j].to])
dfs2(edge2[j].to);
}
struct Point
{
int x,y;
}s[MAXN];
double dist(Point a,Point b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool ok(int n)//判断可行性
{
for(int i=0;i<2*n;i++)
if(!vis1[i])
dfs1(i);
for(int i=Tcnt-1;i>=0;i--)
if(!vis2[T[i]])//这个别写错,是vis2[T[i]]
{
dfs2(T[i]);
Bcnt++;
}
for(int i=0;i<=2*n-2;i+=2)
if(Belong[i]==Belong[i+1])
return false;
return true;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
double left,right,mid;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d%d%d%d",&s[2*i].x,&s[2*i].y,&s[2*i+1].x,&s[2*i+1].y);
left=0;
right=40000.0;
while(right-left>=eps)
{
mid=(left+right)/2;
init();
for(int i=0;i<2*n-2;i++)
{
int t;
if(i%2==0)t=i+2;
else t=i+1;
for(int j=t;j<2*n;j++)
if(dist(s[i],s[j])<2*mid)//冲突了
{
add(i,j^1);
add(j,i^1);//注意顺序不能变的
}
}
if(ok(n))left=mid;
else right=mid;
}
printf("%.2lf
",right);
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
long long read()
{
char ch=getchar();
long long a=0,x=1;
while(ch<'0'||ch>'9')
{
if(ch=='-') x=-x;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
a=(a<<1)+(a<<3)+(ch-'0');
ch=getchar();
}
return a*x;
}
const int N=4e6+5;
int n,m,a,b,x,y,tim,top,edge_sum,scc_sum;
int dfn[N],low[N],st[N],vis[N],scc[N],head[N];
struct node
{
int to,next;
}A[N];
void add(int from,int to)
{
edge_sum++;
A[edge_sum].next=head[from];
A[edge_sum].to=to;
head[from]=edge_sum;
}
void tarjan(int u)
{
dfn[u]=low[u]=++tim;
st[++top]=u;
vis[u]=1;
for(int i=head[u];i;i=A[i].next)
{
int v=A[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
scc_sum++;
while(st[top]!=u)
{
scc[st[top]]=scc_sum;
vis[st[top]]=0;
top--;
}
scc[st[top]]=scc_sum;
vis[st[top]]=0;
top--;
}
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
a=read();x=read(); //第a个数为x或第b个数为y
b=read();y=read();
if(x==0&&y==0) //"如果第a个数为0或第b个数为0"至少满足其一
{
add(a+n,b); //a=1则b=0
add(b+n,a); //b=1则a=0
}
if(x==0&&y==1) //"如果第a个数为0或第b个数为1"至少满足其一
{
add(a+n,b+n); //a=1则b=1
add(b,a); //b=0则a=0
}
if(x==1&&y==0) //"如果第a个数为1或第b个数为0"至少满足其一
{
add(a,b); //a=0则b=0
add(b+n,a+n); //b=1则a=1
}
if(x==1&&y==1) //"如果第a个数为1或第b个数为1"至少满足其一
{
add(a,b+n); //a=0则b=1
add(b,a+n); //b=0则a=1
}
}
for(int i=1;i<=2*n;i++) //对每个变量的每种取值进行tarjan
{
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=n;i++) //判断无解的情况
{
if(scc[i]==scc[i+n]) //同一变量的两种取值在同一强联通分量里,说明无解
{
printf("IMPOSSIBLE
");
return 0;
}
}
printf("POSSIBLE
"); //否则就是有解
for(int i=1;i<=n;i++)
{
if(scc[i]>scc[i+n]) printf("1 "); //强联通分量编号越小 -> 拓扑序越大 -> 越优
else printf("0 ");
}
return 0;
}
莫队
int T, n, m, l, r, siz, lim, bol[MAXN], ans[MAXN], t[MAXN], num[MAXN], a[MAXN];
struct Q {int l, r, x, y, id;} q[MAXN];
void add(int x, int k)
{
for(; x<=1e5+5; x+=(x&-x)) t[x]+=k;
}
int ask(int x)
{
int num=0;
for(; x; x-=(x&-x)) num+=t[x];
return num;
}
bool CMP(Q x, Q y)
{
if(bol[x.l]==bol[y.l]) {
if(bol[x.l]&1) return x.r<y.r;
else return x.r>y.r;
}
return x.l<y.l;
}
int main()
{
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
l=1, r=0, lim=0, siz=max(1, (int)sqrt(n));
for(int i=1; i<=1e5+5; ++i) num[i]=t[i]=0;
for(int i=1; i<=n; ++i) {
scanf("%d", &a[i]);
a[i]++;
bol[i]=(i-1)/siz+1;
}
for(int i=1; i<=m; ++i) {
scanf("%d%d%d%d", &q[i].l, &q[i].x, &q[i].r, &q[i].y);
q[i].x++, q[i].y++;
q[i].id=i;
}
sort(q+1, q+m+1, CMP);
for(int i=1; i<=m; ++i) {
while(r<q[i].r) {
r++;
if(!num[a[r]]) add(a[r], 1);
num[a[r]]++;
}
while(r>q[i].r) {
num[a[r]]--;
if(!num[a[r]]) add(a[r], -1);
r--;
}
while(l<q[i].l) {
num[a[l]]--;
if(!num[a[l]]) add(a[l], -1);
l++;
}
while(l>q[i].l) {
l--;
if(!num[a[l]]) add(a[l], 1);
num[a[l]]++;
}
ans[q[i].id]=ask(q[i].y)-ask(q[i].x-1);
}
for(int i=1; i<=m; ++i) printf("%d
", ans[i]);
}
}
Kruskal 重构树
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
const int maxN = 2e5 + 100;
struct Node
{
int from, to, value, next;
}edge[maxN * 2 + 1], E[maxN * 2 + 1];
int n, m, q;
int tot, head[maxN + 1];
int fa[maxN + 1][20], dep[maxN + 1], lg[maxN + 1];
int cnt, val[maxN + 1], pa[maxN + 1];
inline int read()
{
int num = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar(); }
while(isdigit(ch)) num = (num << 3) + (num << 1) + (ch ^ 48), ch = getchar();
return num * f;
}
inline bool comp(Node a, Node b)
{
return a.value < b.value;
}
inline void add(int x, int y)
{
edge[ ++ tot] = (Node) {x, y, 0, head[x]}; head[x] = tot;
edge[ ++ tot] = (Node) {y, x, 0, head[y]}; head[y] = tot;
}
inline int find(int x) { return pa[x] == x ? x : pa[x] = find(pa[x]); }
inline void dfs(int x, int pa)
{
dep[x] = dep[pa] + 1;
fa[x][0] = pa;
for(int i = 1; (1<<i) <= dep[x]; i++) fa[x][i] = fa[ fa[x][i - 1] ][i - 1];
for(int i = head[x]; i; i = edge[i].next)
if(edge[i].to != pa) dfs(edge[i].to, x);
}
inline int lca(int x, int y)
{
if(dep[x] < dep[y]) swap(x, y);
while(dep[x] != dep[y]) x = fa[x][ lg[ dep[x] - dep[y] ] - 1];
if(x == y) return x;
for(int i = lg[ dep[x] ]; i >= 0; i--)
if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
#undef int
int main()
#define int long long
{
n = read(), m = read(), q = read();
cnt = n;
for(int i = 1; i <= m; i++) E[i].from = read(), E[i].to = read(), E[i].value = read();
sort(E + 1, E + m + 1, comp);
for(int i = 1; i <= n; i++) pa[i] = i;
for(int i = 1; i <= m; i++)
{
int u = E[i].from, v = E[i].to;
u = find(u); v = find(v);
if(u == v) continue;
int node = ++cnt;
pa[u] = pa[v] = pa[node] = node;
val[node] = E[i].value;
add(u, node); add(v, node);
}
for(int i = 1; i <= n; i++) lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
dfs(cnt, 0);
while(q --)
{
int u = read(), v = read();
printf("%lld
", val[ lca(u, v) ]);
}
return 0;
}
带权并查集
int find(int x){
if(x==fa[x]) return x;
int tx=find(fa[x]);
delta[x]=(delta[x]+delta[fa[x]])%3;
return fa[x]=tx;
}
int unio(int x,int y,int type){
if(x>n||y>n) return 1;
if(type==1&&x==y) return 1;
int tx=find(x);
int ty=find(y);
if(tx==ty){
if((delta[y]-delta[x]+3)%3!=type)//也用向量的思维思考,两种动物都在集合里了,判断一下是否与输入的话相一致
//x->y=x->tx+ty->y,因为tx=ty,即根节点相同,所以x与y的关系表示为(-delta[x]+delta[y]+3)%3,与type比较即可
return 1;
else return 0;
}
else {
fa[ty]=tx;
delta[ty]=(delta[x]-delta[y]+type+3)%3;//关键
return 0;
}
}
数论
lks
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 1e6+5;
const int MOD = 1e9+7;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
LL quick_mod(LL a, LL b, LL c)
{
LL ans = 1;
while(b)
{
if(b & 1)
ans = (ans*a)%c;
b>>=1;
a = (a*a)%c;
}
return ans;
}
LL fac[MAXN];
void Get_Fac(LL m)///m!
{
fac[0] = 1;
for(int i=1; i<=m; i++)
fac[i] = (fac[i-1]*i) % m;
}
LL Lucas(LL n, LL m, LL p)
{
LL ans = 1;
while(n && m)
{
LL a = n % p;
LL b = m % p;
if(a < b)
return 0;
ans = ( (ans*fac[a]%p) * (quick_mod(fac[b]*fac[a-b]%p,p-2,p)) ) % p;
n /= p;
m /= p;
}
return ans;
}
int main()
{
LL n, m, p;
Get_Fac(p);
Lucas(n, m, p);///C(n,m)%p
return 0;
}
矩阵逆
#include<iostream>
#include<cstdio>
#include<cmath>
#define re register
#define il inline
#define ll long long
using namespace std;
il ll read(){
ll s=0,f=0;char c=getchar();
while(c<'0'||c>'9') f=(c=='-'),c=getchar();
while(c>='0'&&c<='9') s=(s<<3)+(s<<1)+(c^'0'),c=getchar();
return f?-s:s;
}
const int N=405,mod=1e9+7;
int n;
ll a[N][N<<1];
il ll qpow(ll x,ll k){
ll ans=1;
while(k){
if(k&1) ans=ans*x%mod;
x=x*x%mod;
k>>=1;
}
return ans%mod;
}
il void Gauss_j(){
for(re int i=1,r;i<=n;++i){
r=i;
for(re int j=i+1;j<=n;++j)
if(a[j][i]>a[r][i]) r=j;
if(r!=i) swap(a[i],a[r]);
if(!a[i][i]){puts("No Solution");return;}
int kk=qpow(a[i][i],mod-2); //求逆元
for(re int k=1;k<=n;++k){
if(k==i) continue;
int p=a[k][i]*kk%mod;
for(re int j=i;j<=(n<<1);++j)
a[k][j]=((a[k][j]-p*a[i][j])%mod+mod)%mod;
}
for(re int j=1;j<=(n<<1);++j) a[i][j]=(a[i][j]*kk%mod);
//更新当前行 如果放在最后要再求一次逆元,不如直接放在这里
}
for(re int i=1;i<=n;++i){
for(re int j=n+1;j<(n<<1);++j) printf("%lld ",a[i][j]);
printf("%lld
",a[i][n<<1]);
}
}
int main(){
n=read();
for(re int i=1;i<=n;++i)
for(re int j=1;j<=n;++j)
a[i][j]=read(),a[i][i+n]=1;
Gauss_j();
return 0;
}
void ins(ll num){
for(ll i = 63;i >= 0;i--)//枚举位数
if(num & (1ll << i)){ //注意这里的1ll
if(!p[i]){p[i] = num;break;}
num ^= p[i];
}
}
inline int ask(LL x) {
for(R int i=62;i>=0;i--)
if(x&(1LL<<i)) x^=p[i];
return x==0;
}
void get(){//从高到低 贪心选择
for(ll i = 63;i >= 0;i--)
ans = max(ans,ans ^ p[i]);
}
inline LL askmn() {
if(zero) return 0;
for(R int i=0;i<=62;i++)
if(p[i]) return p[i];
}
inline void rebuild() {//求k大
cnt=0;top=0;
for(R int i=MB;i>=0;i--)
for(R int j=i-1;j>=0;j--)
if(p[i]&(1LL<<j)) p[i]^=p[j];
for(R int i=0;i<=MB;i++) if(p[i]) d[cnt++]=p[i];
}
millerrabin
#include <bits/stdc++.h>
using namespace std;
#define N 10
typedef long long LL;
LL random(LL n)
{
return (LL)((double)rand()/RAND_MAX*n+0.5);
}
LL multi(LL a,LL b,LL m) //计算a*b%m
{
LL ret=0;
while(b)
{
if(b&1) ret=(ret+a)%m;
b>>=1;
a=(a<<1)%m;
}
return ret;
}
LL quick_mod(LL a,LL b,LL m) //计算a^b%m
{
LL ans=1;
while(b)
{
if(b&1)
{
ans=multi(ans,a,m);
b--;
}
b>>=1;
a=multi(a,a,m);
}
return ans;
}
bool miller_rabin(LL n)
{
if(n==2) return true;
if(n<2||!(n&1)) return false;
LL m=n-1;
int k=0;
while((m&1)==0)
{
k++;
m>>=1;
}
for(int i=0; i<N; i++)
{
LL a=rand()%(n - 1)+1;
LL x=quick_mod(a,m,n);
LL y=0;
for(int j=0;j<k;j++)
{
y=multi(x,x,n);
if(y==1&&x!=1&&x!=n-1) return false;
x=y;
}
if(y!=1) return false;
}
return true;
}
int main()
{
LL n;
int T;cin>>T;
while(T--) {
cin>>n;
if(miller_rabin(n)) puts("Yes");
else puts("No");
}
return 0;
}
逆元:
tmp[1]=1;
cout<<1<<endl;
for( i=2;i<=n;i++)
tmp[i]=(long long)(p-p/i)*tmp[p%i]%p,printf("%d
",tmp[i]);
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;
}
int main() {
ll x, y;
Exgcd (a, p, x, y);
x = (x % p + p) % p;
printf ("%d
", x); //x是a在mod p下的逆元
}
int phi(int n)
{
int rea = n;
for(int i = 2;i*i <=n;i++)
if(n%i == 0)
{
rea = rea - rea/i;
do
n /= i;
while(n%i == 0);
}
if(n > 1)
rea = rea - rea/n;
return rea;
}
二分//别搞错
while(l<=r){
int x=(l+r)>>1;
if(check(x))
r=x-1;
else
l=x+1;
}
线段树(doge) 优先级:区间赋值>区间乘>区间加。
#include <bits/stdc++.h>
#define LL long long
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define N 100005
using namespace std;
int sum[N * 4], add[N * 4], col[N * 4], mul[N * 4];
void pushup(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void pushdown(int rt, int x){
if(col[rt] != -1){
add[rt<<1] = add[rt<<1|1] = 0;
mul[rt<<1] = mul[rt<<1|1] = 1;
sum[rt<<1] = col[rt] * (x - x / 2);
sum[rt<<1|1] = col[rt] * (x / 2);
col[rt<<1] = col[rt<<1|1] = col[rt];
col[rt] = -1;
}
if(mul[rt] != 1){
int c = mul[rt];
mul[rt<<1] *= c;
mul[rt<<1|1] *= c;
sum[rt<<1] *= c;
sum[rt<<1|1] *= c;
add[rt<<1] *= c;
add[rt<<1|1] *= c;
mul[rt] = 1;
}
if(add[rt]){
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt] * (x - x / 2);
sum[rt<<1|1] += add[rt] * (x / 2);
add[rt] = 0;
}
}
void build(int l, int r, int rt){
if(l == r){
scanf("%d", &sum[rt]);
return;
}
int m = l + r >> 1;
build(lson);
build(rson);
pushup(rt);
}
void update(int l, int r, int rt, int a, int b, int c, int o){
if(l >= a && r <= b){
if(o == 1){//set
add[rt] = 0;
mul[rt] = 1;
sum[rt] = c * (r - l + 1);
col[rt] = c;
}
else if(o == 2){//cheng
mul[rt] *= c;
sum[rt] *= c;
add[rt] *= c;
}
else{//jia
add[rt] += c;
sum[rt] += c * (r - l + 1);
}
return;
}
pushdown(rt, r-l+1);
int m = l + r >> 1;
if(a <= m) update(lson, a, b, c, o);
if(b > m) update(rson, a, b, c, o);
pushup(rt);
}
int query(int l, int r, int rt, int a, int b){
if(l >= a && r <= b) return sum[rt];
pushdown(rt, r-l+1);
int m = l + r >> 1, ans = 0;
if(a <= m) ans += query(lson, a, b);
if(b > m) ans += query(rson, a, b);
return ans;
}
int main(){
int i, j, n, m, o, a, b, c;
scanf("%d%d", &n, &m);
for(i = 1; i <= n * 4; i++){
mul[i] = 1;
col[i] = -1;
}
build(1, n, 1);
while(m--){
scanf("%d%d%d", &o, &a, &b);
if(o == 4) printf("%d
", query(1, n, 1, a, b));
else{
scanf("%d", &c);
update(1, n, 1, a, b, c, o);
}
}
return 0;
}
莫队
//1.建块
ps:
(del){
vector <int>::iterator it=lower_bound(p[blo[x]].begin(),p[blo[x]].end(),a[x]);
p[blo[x]].erase(it);
}
inline void build() {
memset(minn,0x7f,sizeof(minn));
block=sqrt(n);//block记录每一块的长度
num=n/block;//num记录块的个数
if(n%block) ++num;//没有平均分成多块的情况
for(int i=1 ; i<=n ; ++i) {
belong[i]=(i-1)/block+1;//每个点属于哪一块
}
for(int i=1 ; i<=num ; ++i) {
left[i]=(i-1)*block+1;
right[i]=i*block;//每块的左右边界
}
right[num]=n;//单独处理最后一块右边界
for(int i=1 ; i<=num ; ++i) {
for(int j=left[i] ; j<=right[i] ; ++j) {
minn[i]=min(minn[i],a[j]);//首先取得每块中的最小值
}
}
}
//2.区间修改
这里需要用到一个类似于线段树中 lazy_tag 的标记,否则分块就跟暴力模拟的速度一样了
inline void modify(int l,int r,int v) {
if(belong[l]==belong[r]) {//处理特殊情况(查询区间完全被某一块覆盖)
for(int i=l ; i<=r ; ++i) {
a[i]+=v;
minn[belong[l]]=min(minn[belong[l]],a[i]);
}
return ;
}
for(int i=l ; i<=right[belong[l]] ; ++i) {
a[i]+=v;
minn[belong[l]]=min(minn[belong[l]],a[i]);
}//处理左边界所在块
for(int i=belong[l]+1 ; i<belong[r] ; ++i) {
add[i]+=v;
}//add就是lazy_tag,表示整个区间所加上的值
for(int i=left[belong[r]] ; i<=r ; ++i) {
a[i]+=v;
minn[belong[r]]=min(minn[belong[r]],a[i]);
}//处理右边界所在块
}
//3.区间查询
inline int query(int l,int r) {
int ans=0x7fffffff;
if(belong[l]==belong[r]) {
for(int i=l ; i<=r ; ++i) {
ans=min(ans,a[i]);
}
return ans;
}
for(int i=l ; i<=right[belong[l]] ; ++i) {
ans=min(ans,a[i]+add[belong[i]]);
}
for(int i=belong[l]+1 ; i<belong[r] ; ++i) {
ans=min(ans,minn[i]+add[i]);
}
for(int i=left[belong[r]] ; i<=r ; ++i) {
ans=min(ans,a[i]+add[belong[i]]);
}
return ans;
}
网络流
#include<bits/stdc++.h>
#define ll long long
#define N 110000
using namespace std;
ll n,m,s,t,x,y,z,tot=1,head[N],hd[N],dep[N],inf=0x7fffffff;
struct node{
ll to,dis,nxt;
}e[5*N];
void add(ll f,ll to,ll dis){
e[++tot].to=to;
e[tot].dis=dis;
e[tot].nxt=head[f];
head[f]=tot;
}
ll bfs(){
memcpy(hd,head,sizeof(hd));
memset(dep,0,sizeof(dep));
queue<ll>q;
dep[s]=1;
q.push(s);
while(!q.empty()){
ll u=q.front();
q.pop();
for(ll i=head[u];i;i=e[i].nxt){
ll v=e[i].to;
if(!dep[v]&&e[i].dis>0){
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return dep[t];
}
ll dfs(ll u,ll lim){
if(u==t||!lim)return lim;
ll flow=0;
for(ll i=hd[u];i&&lim;i=e[i].nxt){
hd[u]=i;
ll v=e[i].to,ff;
if(dep[v]==dep[u]+1&&(ff=dfs(v,min(lim,e[i].dis)))){
lim-=ff;
e[i].dis-=ff;
e[i^1].dis+=ff;
flow+=ff;
}
}
return flow;
}
ll dinic(){
ll sum=0;
while(bfs())sum+=dfs(s,inf);
return sum;
}
int main(){
scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
for(ll i=1;i<=m;i++){
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
add(y,x,0);
}
printf("%lld",dinic());
}
SPFA
void spfa_bfs(int st)
{
memset(inque,0,sizeof(inque));
dis[st]=0;
queue<int> que;
que.push(st);
int u,v,i;
while(!que.empty())
{
u=que.front();que.pop();
inque[u]=0;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(dis[v]>dis[u]+edge[i].val)
{
dis[v]=dis[u]+edge[i].val;
if(!inque[v])
{
que.push(v);
inque[v]=1;
}
}
}
}
}
TOPSORT
for(register int i = 1; i <= m; ++i)
{
scanf("%d %d", &x, &y);
++in[y];
add(x, y);
}
for(register int i = 1; i <= n; ++i)
{
if(in[i] == 0)
{
pru.push(i);
dis[i] = 1;
}
}
while(!pru.empty())
{
int u = pru.front();
pru.pop();
for(register int i = head[u]; i; i = stu[i].next)
{
int k = stu[i].to;
--in[k];
if(in[k] == 0)
{
pru.push(k);
dis[k] = dis[u] + 1;
}
}
}
prim(doge)
while (count < nodeNum) {
int min = init;
//寻找最小权值顶点
for (int i = 1; i <= nodeNum; i++) {
if (visited[i] == 0 && dis[i] < min) {
min = dis[i];
j = i;
}
}
visited[j] = 1;
count++;
sum = sum + dis[j];
A.push_back(j);
//更新dis矩阵
for (int i = 1; i <= nodeNum; i++) {
if (visited[i] == 0 && dis[i] > adjMatrix[j][i]) {
dis[i] = adjMatrix[j][i];
}
}
}
DJ+堆
void DJ(){
priority_queue<pair<int,int>>Q;
Q.push(make_pair(0,1));
while(!Q.empty()){
int u=Q.top().second;
Q.pop();
if(In[u])continue;
In[u]=1;
for(int i=0;i<v1[u].size();i++){
int v=v1[u][i];
if(Dis[v]>Dis[u]+v2[u][i]){
Dis[v]=Dis[u]+v2[u][i];
if(!In[v])
Q.push(make_pair(-Dis[v],v));
}
}
}
printf("%d
",Dis[n]);
}
线性筛(欧拉筛法)
线性筛是在埃氏筛法的基础上,让每一个合数,只被它的最小质因子筛选一次,达到不重复的目的。
怎么理解呢?根据最开始所说的整数的唯一分解定理,每个合数有且只有一组质数相乘可以得到,前面的埃氏筛法,每一个质因子都要筛掉该合数一次,我们如果让每个合数只被它最小的质因子筛选就完全避免了埃氏筛法的重复。从算法来说,N范围内的每个数都只会被筛一次,所以算法复杂度是O(n)。
bool vis[maxN];
int prime[maxN],cnt;
void init()
{
memset(vis,false, sizeof(vis));//所有数初始化为0->质数
vis[0]=true;
vis[1]=true;
cnt=0;
}
void Is_Prime()
{
init();
for(int i=2;i<=N;i++)
{
if(!vis[i])//i是质数
prime[++cnt]=i;//prime是用来存质数的数组,显然数组中的质数是从小到大
for(int j=1;j<=cnt;j++)
{
if(i*prime[j]>N)
break;
vis[i*prime[j]]=true;
if(i % prime[j] == 0)
break;
}
}
}
离散化
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
t[i]=a[i];
}
sort(t+1,t+1+n);
int len=unique(t+1,t+1+n)-t-1;// -1
for(int i=1;i<=n;i++)
a[i]=lower_bound(t+1,t+1+len,a[i])-t; // -t
kmp
#include <bits/stdc++.h>
using namespace std;
int main() {
string a,b;
while (cin >> a) {
if (a =="#") break;
cin >> b;
int ans= 0;
while (a.find(b) != -1) {
a.erase(a.begin(), a.begin() + (a.find(b) + b.size()));
ans++;
}
printf("%d
",ans);
}
return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int lena, lenb, nxt[1000005];
char a[1000005], b[1000005];
void mknxt(){
int j=0, k;
k = nxt[0] = -1;
while(j<lenb){
if(k==-1 || b[j]==b[k]) nxt[++j] = ++k;
else k = nxt[k];
}
}
void kmp(){
int i=0, j=0;
while(i<lena){
if(j==-1 || a[i]==b[j]) i++, j++;
else j = nxt[j];
if(j==lenb) printf("%d
", i-j+1), j = nxt[j];
}
}
int main(){
scanf("%s %s", a, b);
lena = strlen(a);
lenb = strlen(b);
mknxt();
kmp();
for(int i=1; i<=lenb; i++) printf("%d ", nxt[i]);
return 0;
}
hash
map<unsigned long long , bool >Map;
const unsigned long long base = 19260817;
ull Hash[N],pw[N];
void Pre(){
pw[0]=1;
for(int i=1;i<=(1000000);i++) {
pw[i]=pw[i-1]*base;
}
}
void InMap(){
Map.clear();
for(int i=1;i<=n;i++) {
Hash[i]=Hash[i-1]*base+'1'-s[i];
}
for(int i=k;i<=n;i++) {
Map [Hash[i]-Hash[i-k]*pw[k]] = true;
}
}
高斯消元
#include<bits/stdc++.h>
#define db double
using namespace std;
int n,w[105];
db a[105][105],ans[105];
const db ex=1e-6;
void Gauss(){
for(int i=1;i<=n;i++){
int p=-1;db mx=0;
for(int j=1;j<=n;j++){//找该行最大
if(fabs(a[i][j])>mx+ex)
mx=fabs(a[i][j]),p=j;//***FFFFFF
}
if(p==-1){puts("No Solution");exit(0);}
w[i]=p;
for(int j=1;j<=n;j++){//与每一行消
if(i!=j){
db t=a[j][p]/a[i][p];
for(int k=1;k<=n+1;k++){
a[j][k]-=t*a[i][k];
}
}
}
}
for(int i=1;i<=n;i++){
ans[w[i]]=a[i][n+1]/a[i][w[i]];
}
for(int i=1;i<=n;i++)printf("%.2lf
",ans[i]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
cin>>a[i][j];
Gauss();
}
边双点双
int low[maxn],dfn[maxn],cnt=0;
bool bridge[maxm<<1];
void tarjan(int x,int in_edge){
dfn[x]=low[x]=++cnt;
for(int i=head[x];i+1;i=a[i].next){
int y=a[i].y;
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>low[x])bridge[i]=bridge[i^1]=true;
}
else if(i!=(in_edge^1))
low[x]=min(low[x],dfn[y]);
}
}
int block[maxn],dcc=0;
void dfs(int x,int color){
block[x]=color;
for(int i=head[x];i+1;i=a[i].next){
int y=a[i].y;
if(bridge[i])continue;
if(!block[y])dfs(y,color);
}
}
void get_edccs(){
for(int i=1;i<=n;i++)
if(!block[i])
dfs(i,++dcc);
}
void tarjan(int x,int in_edge){
low[x]=dfn[x]=++cnt;sta[++t]=x;
for(int i=head[x];i+1;i=a[i].next){
int y=a[i].y;
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
int u;
dcc++;size=0;
vdcc.clear();
do{
u=sta[t--];
block[u]=dcc;
size++;
vdcc.push_back(u);
}while(u!=y);
block[x]=dcc;
vdcc.push_back(x);
size++;
work();
}
}
else low[x]=min(low[x],dfn[y]);
}
}
tarjan
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int INF=2e9;
vector<int>E[maxn];
struct point{
int x,y,r,co;
}boom[maxn];
int dfn[maxn],low[maxn],id,vis[maxn],ans,deg[maxn];
int num[maxn],cnt,cost[maxn];
stack<int>s;
bool ju(point a,point b){
return (1ll*(a.x-b.x)*(a.x-b.x)+1ll*(a.y-b.y)*(a.y-b.y)<=1ll*a.r*a.r);
}
void init(){
id=cnt=0;
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(deg,0,sizeof(deg));
memset(num,0,sizeof(num));
}
void tarjan(int u){
low[u]=dfn[u]=++id;
s.push(u);
vis[u]=1;
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
int minco=INF;
cnt++;
while(1){
int Top=s.top();
s.pop();
vis[Top]=0;
num[Top]=cnt;
minco=min(minco,boom[Top].co);
if(Top==u)break;
}
cost[cnt]=minco;
}
}
int main(){
int T;
cin>>T;
for(int Case=1;Case<=T;Case++){
init();
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&boom[i].x,&boom[i].y,&boom[i].r,&boom[i].co);
E[i].clear();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
if(ju(boom[i],boom[j]))E[i].push_back(j);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++){
for(int j=0;j<E[i].size();j++){
int v=E[i][j];
if(num[i]!=num[v]) deg[num[v]]=1;
}
}
ans=0;
for(int i=1;i<=cnt;i++) if(deg[i]==0)
ans+=cost[i];
printf("Case #%d: %d
",Case,ans);
}
return 0;
}
求割边
const int maxn = 1e5 + 10;
vector<vector<int> > G;
int dfn[maxn], low[maxn], isbridge[maxn], mark[maxn], depth;
int pre[maxn];
int bridge_cnt;
void dfs(int u, int fa) {
dfn[u] = low[u] = ++depth;
mark[u] = 1;
int first = 1;
int size = G[u].size();
for (int i = 0;i < size;++i) {
int v = G[u][i];
if (first && v == fa) {
first = 0;
continue;
}
if (dfn[v] == -1) {
pre[v] = u;
dfs(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u]) {//is bridge
isbridge[v] = 1;
bridge_cnt++;
}
}else if (mark[v]) low[u] = min(low[u], dfn[v]);
}
}
int calc(int u,int v) {
int ret = 0;
if (dfn[u] < dfn[v]) swap(u, v);
while(dfn[u] > dfn[v]) {
if (isbridge[u]) {
isbridge[u] = 0;
ret++;
}
u = pre[u];
}
while(dfn[v] > dfn[u]) {
if (isbridge[v]) {
isbridge[v] = 0;
ret++;
}
v = pre[v];
}
return ret;
}
int main(int argc, const char * argv[])
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// clock_t _ = clock();
int n, m;
while(scanf("%d%d", &n, &m) != EOF && n + m) {
G.clear();
G.resize(n + 2);
int u, v;
for (int i = 1;i <= m;++i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(dfn, -1,sizeof dfn);
memset(isbridge, 0, sizeof isbridge);
memset(mark, 0,sizeof mark);
depth = 0, bridge_cnt = 0;
dfs(1, -1);
scanf("%d", &m);
printf("Case %d:
", ++nCase);
while(m--) {
scanf("%d%d", &u, &v);
int cnt = calc(u, v);
bridge_cnt -= cnt;
printf("%d
", bridge_cnt);
}
printf("
");
}
// printf("
Time cost: %.2fs
", 1.0 * (clock() - _) / CLOCKS_PER_SEC);
return 0;
}
求割点
#include<bits/stdc++.h>
using namespace std;
struct edge{
int nxt,mark;
}pre[200010];
int n,m,idx,cnt,tot;
int head[100010],DFN[100010],LOW[100010];
bool cut[100010];
void add (int x,int y)
{
pre[++cnt].nxt=y;
pre[cnt].mark=head[x];
head[x]=cnt;
}
void tarjan (int u,int fa)
{
DFN[u]=LOW[u]=++idx;
int child=0;
for (int i=head[u];i!=0;i=pre[i].mark)
{
int nx=pre[i].nxt;
if (!DFN[nx])
{
tarjan (nx,fa);
LOW[u]=min (LOW[u],LOW[nx]);
if (LOW[nx]>=DFN[u]&&u!=fa)
cut[u]=1;
if(u==fa)
child++;
}
LOW[u]=min (LOW[u],DFN[nx]);
}
if (child>=2&&u==fa)
cut[u]=1;
}
int main()
{
memset (DFN,0,sizeof (DFN));
memset (head,0,sizeof (head));
scanf ("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int a,b;
scanf ("%d%d",&a,&b);
add (a,b);
add (b,a);
}
for (int i=1;i<=n;i++)
if (DFN[i]==0)
tarjan (i,i);
for (int i=1;i<=n;i++)
if (cut[i])
tot++;
printf ("%d
",tot);
for (int i=1;i<=n;i++)
if (cut[i])
printf ("%d ",i);
return 0;
}
最小费用最大流
include<bits/stdc++.h>
define ll long long
define N 110000
using namespace std;
ll n,m,s,t,x,y,z,w,tot=1,mxf,mnc,head[N],hd[N],dis[N],flow[N],pre[N],last[N],inf=0x7fffffff;
bool vis[N];
struct node{
ll f,to,dis,nxt;
}e[5N];
void add(ll f,ll to,ll fl,ll dis){
e[++tot].to=to;
e[tot].dis=dis;
e[tot].nxt=head[f];
e[tot].f=fl;
head[f]=tot;
}
bool spfa(){
memset(dis,0x7f,sizeof(dis));
memset(flow,0x7f,sizeof(flow));
memset(vis,0,sizeof(vis));
queue
vis[s]=1;dis[s]=0;pre[t]=0;
q.push(s);
while(!q.empty()){
ll u=q.front();
q.pop();
for(ll i=head[u];i;i=e[i].nxt){
ll v=e[i].to;
if(dis[v]>dis[u]+e[i].dis&&e[i].f>0){
dis[v]=dis[u]+e[i].dis;
pre[v]=u;
last[v]=i;
flow[v]=min(flow[u],e[i].f);
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
vis[u]=0;
}
return pre[t];
}
void dinic(){
while(spfa()){
ll u=t;
mxf+=flow[t];
mnc+=flow[t]
while(u!=s){
e[last[u]].f-=flow[t];
e[last[u]^1].f+=flow[t];
u=pre[u];
}
}
}
int main(){
scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
for(ll i=1;i<=m;i++){
scanf("%lld%lld%lld%lld",&x,&y,&z,&w);
add(x,y,z,w),add(y,x,0,-w);
}
dinic();
printf("%lld %lld",mxf,mnc);
}
单调队列
#include<bits/stdc++.h>
#define MAXN 1000009
using namespace std;
int q[MAXN],h,t,n,k,a[MAXN];
int minn()
{
h=1,t=0;
q[1]=1;
for(int i=1;i<=n;i++)
{
if(i-q[h]==k)
h++;
if(t==h-1||a[i]>a[q[t]])//t==h-1??
{
t++;
q[t]=i;
}
else
{
while(t>=h&&a[i]<=a[q[t]])
{
q[t]=i;
t--;
}
t++;
}
if(i>=k)
printf("%d ",a[q[h]]);
}
}
int maxx()
{
h=1,t=0;
q[1]=1;
for(int i=1;i<=n;i++)
{
if(i-q[h]==k)
h++;
if(t==h-1||a[i]<a[q[t]])//t==h-1??
{
t++;
q[t]=i;
}
else
{
while(t>=h&&a[i]>=a[q[t]])
{
q[t]=i;
t--;
}
t++;
}
if(i>=k)
printf("%d ",a[q[h]]);
}
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
minn();
cout<<endl;
maxx();
return 0;
}
AC自动机
1:TRIE
void insert(int ct){
root=0;ans=ct;
for(int i=0;i<=len;i++){
id=get(i);
if(!trie[root][id]){
trie[root][id]=++tot;
memset(trie[tot],0,sizeof(trie[tot]));
sum[tot]=0;mark[tot]=0;
}
root=trie[root][id];
ans+=sum[root]<<1;
sum[root]++;
}
ans+=mark[root];
mark[root]++;
}
#include<bits/stdc++.h>
using namespace std;
#define N 100003
int n,tot,len[N];
string T;
char S[N][51];
struct trie{
int son[27],fail,val;
}tr[N*51];
queue<int>Q;
void maketrie(){
int root=0;
memset(tr[0].son,0,sizeof(tr[0].son));
tr[0].fail=tr[0].val=0;
for(int i=1;i<=n;i++){
root=0;
for(int p=0;p<len[i];++p){
int k=S[i][p]-'a';
if(!tr[root].son[k]){
memset(tr[tot+1].son,0,sizeof(tr[tot+1].son));
tr[tot+1].fail=tr[tot+1].val=0;
tr[root].son[k]=++tot;
}
root=tr[root].son[k];
}
tr[root].val++;
}
}
void makefail(){
while(!Q.empty())Q.pop();
for(int i=0;i<26;i++){
if(tr[0].son[i]){
tr[tr[0].son[i]].fail=0;
Q.push(tr[0].son[i]);
}
}
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=0;i<26;++i){
if(tr[u].son[i]){
tr[tr[u].son[i]].fail=tr[tr[u].fail].son[i];
Q.push(tr[u].son[i]);
}
else
tr[u].son[i]=tr[tr[u].fail].son[i];
}
}
}
int query(string t){
int le=t.length(),ans=0,u=0,k;
for(int i=0;i<le;i++)
{
k=T[i]-'a';u=tr[u].son[k];
for(int p=u;p&&tr[p].val!=-1;p=tr[p].fail)
{
ans+=tr[p].val;
tr[p].val=-1;
}
}return ans;
}
int main(){
int Ti;cin>>Ti;
while(Ti--){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%s",S[i]);
len[i]=strlen(S[i]);
}
cin>>T;
maketrie();
makefail();
cout<<query(T)<<endl;
}
}
最大二分图匹配
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m,e,u,v,ans,match[N];
bool a[N][N],vis[N];
bool dfs(int x) {
for(int i=1;i<=m;i++)if(!vis[i]&&a[x][i]){
vis[i]=1;
if(!match[i]||dfs(match[i])){
match[i]=x;
return 1;
}
}
return 0;
}
int main() {
scanf("%d %d %d",&n,&m,&e);
for(int i=1;i<=e;i++)scanf("%d %d",&u,&v),a[u][v]=1;
for (int i=1; i<=n;i++){
ans+=dfs(i);
memset(vis,0,sizeof(vis));
}
printf("%d",ans);
}
EXCRT
#include<bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
ll a[N],m[N],n;
ll exgcd(ll aa,ll bb,ll &x,ll &y){
if(!bb){
x=1;y=0;return aa;
}
ll r=exgcd(bb,aa%bb,y,x);
y-=x*(aa/bb);
return r;
}
ll mul (ll aa,ll bb,ll mod){
ll r=0;
while(bb){
if(bb&1) r=(r+aa)%mod;
aa=(aa*2)%mod;
bb>>=1;
}return r;
}
ll crt(){
ll M=m[1],A=a[1],t,d,x,y;
for(int i=2;i<=n;i++)
{
ll aa=M,b=m[i],c=((a[i]-A)%b+b)%b;//不搞这个%b会爆(TLE)
d=exgcd(aa,b,x,y);
t=b/d;
if((c%d)!=0)return -1;//no solution
x=mul(x,c/d,t);
A+=x*M;
M=M*t;
A=(A%M+M)%M;
//A要变成原来求的第一个x,原来的第一个x变成余数,声称该式变成:X≡(a1x1+b1)(mod(lcm(a1,a2)))
}
A=(A%M+M)%M;
return A;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)scanf("%lld%lld",&m[i],&a[i]);
printf("%lld
",crt());
}
凸包
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1000;
struct Knight {
int x;
int y;
}p[maxn], s[maxn];
int cross_product(Knight a, Knight b, Knight c) {
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
double dis(Knight a, Knight b) {
return sqrt((a.x - b.x) * (a.x - b.x) * 1.0 + (a.y - b.y) * (a.y - b.y) * 1.0);
}
int cmp1(Knight a, Knight b) {
if(a.y == b.y)
return a.x < b.x;
return a.y < b.y;
}
int cmp2(Knight a, Knight b) {
int m = cross_product(s[0], a, b);
if(m > 0){
return 1;
}else if(m == 0 && dis(s[0], a) - dis(s[0], b) <= 0){
return 1;
}else{
return 0;
}
}
/*
//x和y为找到的纵坐标最小坐标,即基准点(原点)
int cmp2(Knight a, Knight b) {
if(atan2(a.y - y, a.x - x) != atan2(b.y - y, b.x - x))
return (atan2(a.y - y, a.x - x)) < (atan2(b.y - y, b.x - x));
return a.x < b.x;
}
*/
int main() {
int n;
while(scanf("%d", &n) != EOF && n) {
for(int i = 0; i < n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
}
if(n == 1) {//只有一个点的时候,就没有周长啦
printf("0.00
");
}else if(n == 2) {//两个点就可以直接计算出答案啦
printf("%.2lf
", dis(p[0], p[1]));
}else{
memset(s, 0, sizeof(s));
sort(p, p+n, cmp1);//排序找出纵坐标最小的值
s[0] = p[0];
sort(p + 1, p + n, cmp2);//剩下的点进行极角排序
s[1] = p[1];//这是找到的p1点
int top = 1;
for(int i = 2; i < n; i++){
while(cross_product(s[top-1], s[top], p[i]) < 0){
top--;//如果是向右转,这个中间点就不是我们要找的点
}
s[++top]=p[i];//如果是向左转,就加进来
}
double ans = 0;
for(int i = 0; i < top; i++){//计算两点之间的距离
ans += dis(s[i], s[i + 1]);
}
ans += dis(s[0], s[top]);//别忘记把最后一个点和第一个点连起来
printf("%.2lf
",ans);
}
}
}
可持久化线段树
v#include<bits/stdc++.h>
using namespace std;
const int MX=1000009;
int rt[MX],a[MX],n,m,tot;
struct sgtree{
int val,ls,rs;
}t[MX*20];
void built(int &now,int l,int r){
now=++tot;
if(l==r){
scanf("%d",&t[now].val);return;
}
int mid=(l+r)>>1;
built(t[now].ls,l,mid);//build son
built(t[now].rs,mid+1,r);
}
void ins(int &now,int lst,int l,int r,int pos,int val){
now=++tot;t[now]=t[lst];
if(l==r){
t[now].val=val;return;
}
int mid=(l+r)>>1;
if(pos<=mid) ins(t[now].ls,t[lst].ls,l,mid,pos,val);
else ins(t[now].rs,t[lst].rs,mid+1,r,pos,val);
}
int query(int now,int l,int r,int pos){
if(l==r) return t[now].val;
int mid=(l+r)>>1;
if(pos<=mid) return query(t[now].ls,l,mid,pos);
else return query(t[now].rs,mid+1,r,pos);
}
int main(){
cin>>n>>m;
built(rt[0],1,n);
for(int i=1;i<=m;i++){
int ver,op,pos;
scanf("%d%d%d",&ver,&op,&pos);
if(op==1)
{
int u;scanf("%d",&u);
ins(rt[i],rt[ver],1,n,pos,u);
}else
printf("%d
",query(rt[ver],1,n,pos)),rt[i]=rt[ver];
}return 0;
}
ST表
k=int(log2(y-x+1));
ans[i]=max(a[x][k],a[y-(1<<k)+1][k]);
树链剖分
void wk2(int u){
res=0;
query(1,1,n,id[u],id[u]+siz[u]-1);
printf("%d
",siz[u]-res);
upd(1,1,n,id[u],id[u]+siz[u]-1,1);
}
void wk1(int u){
res=0;
int v=1,ans=0,tp=u;
while(topf[u]!=topf[v]){
query(1,1,n,id[topf[u]],id[u]);
u=fa[topf[u]];
}
query(1,1,n,id[v],id[u]);
printf("%d
",res);
u=tp;
while(topf[u]!=topf[v]){
upd(1,1,n,id[topf[u]],id[u],0);
u=fa[topf[u]];
}
upd(1,1,n,id[v],id[u],0);
}
#include<bits/stdc++.h>
#define M 100005
#define mid ((l+r)>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
int bok,n,m,pr[M*5],h[M*2],cnt,ct,siz[M],son[M],fa[M],dep[M],topf[M],id[M],sm[M*5],lazy[M*5],res,co[M],lc[M*5],rc[M*5];
inline int gi(){
int re=0,f=1;
char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')f=0,c=getchar();
while(c>='0'&&c<='9')re=re*10+c-'0',c=getchar();
return f?re:-re;
}
struct ee{
int t,nxt;
}e[M*2];
void add(int fr,int t){
e[++ct].t=t;
e[ct].nxt=h[fr];
h[fr]=ct;
}
void dfs1(int u,int ff,int dp){
dep[u]=dp;
siz[u]=1;
fa[u]=ff;
for(int i=h[u];i;i=e[i].nxt){
int v=e[i].t;
if(v!=ff){
dfs1(v,u,dp+1);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int top){
++cnt;
id[u]=cnt;
pr[cnt]=co[u];
topf[u]=top;
if(!son[u])return;
dfs2(son[u],top);
for(int i=h[u];i;i=e[i].nxt){
int v=e[i].t;
if(v!=fa[u]&&v!=son[u]){
dfs2(v,v);
}
}
}
void built(int k,int l,int r){
if(l==r){
lc[k]=rc[k]=pr[l];
sm[k]=1;
return;
}
built(lson);
built(rson);
lc[k]=lc[k<<1];
rc[k]=rc[k<<1|1];
sm[k]=sm[k<<1]+sm[k<<1|1]-(rc[k<<1]==lc[k<<1|1]);
}
void pushdown(int k,int len){
lazy[k<<1|1]=lazy[k<<1]=lazy[k];
sm[k<<1]=1;
sm[k<<1|1]=1;//****1
lc[k<<1]=rc[k<<1|1]=lazy[k];
rc[k<<1]=lc[k<<1|1]=lazy[k];
lazy[k]=0;
}
void upd(int k,int l,int r,int L,int R,int chang){
if(L<=l&&R>=r){
lc[k]=rc[k]=chang;
sm[k]=1;
lazy[k]=chang;return;
}
if(lazy[k])
pushdown(k,r-l+1);
if(L<=mid)//***
upd(lson,L,R,chang);
if(R>mid)//***
upd(rson,L,R,chang);
lc[k]=lc[k<<1];
rc[k]=rc[k<<1|1];
sm[k]=sm[k<<1]+sm[k<<1|1]-(rc[k<<1]==lc[k<<1|1]);
}
void query(int k,int l,int r,int L,int R){
if(L<=l&&R>=r){
res+=sm[k];
return;
}
if(lazy[k])
pushdown(k,r-l+1);
if(L<=mid)
query(lson,L,R);
if(R>mid)//***
query(rson,L,R);
res-=(L<=mid&&R>mid&&rc[k<<1]==lc[k<<1|1]);
}
void query2(int k,int l,int r,int L,int R){
if(l==r){
bok=lc[k];
return;
}
if(lazy[k])
pushdown(k,r-l+1);
if(L<=mid)
query2(lson,L,R);
if(R>mid)//***
query2(rson,L,R);
}
void wk1(int a,int b,int c){
while(topf[a]!=topf[b]){
if(dep[topf[a]]>dep[topf[b]])
swap(a,b);
upd(1,1,n,id[topf[b]],id[b],c);
b=fa[topf[b]];
}
if(dep[a]>dep[b])swap(a,b);
upd(1,1,n,id[a],id[b],c);
}
void wk2(int a,int b){
res=0;
while(topf[a]!=topf[b]){
if(dep[topf[a]]>dep[topf[b]])
swap(a,b);
query(1,1,n,id[topf[b]],id[b]);
int b1,b2;
query2(1,1,n,id[topf[b]],id[topf[b]]),b1=bok;
query2(1,1,n,id[fa[topf[b]]],id[fa[topf[b]]]),b2=bok;
if(b1==b2)--res;
b=fa[topf[b]];
}
if(dep[a]>dep[b])swap(a,b);
query(1,1,n,id[a],id[b]);
printf("%d
",res);
}
int main(){
n=gi();m=gi();
for(int i=1;i<=n;i++)
co[i]=gi();
for(int i=1;i<n;i++){
int u=gi(),v=gi();
add(u,v);
add(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
built(1,1,n);
char op;
for(int i=1;i<=m;i++){
cin>>op;
if(op=='C'){
int a,b,c;
a=gi();b=gi();c=gi();
wk1(a,b,c);
}else{
int a,b;
a=gi();b=gi();
wk2(a,b);
}
}
}
#include<bits/stdc++.h>
#define M 50005
#define mid ((l+r)>>1)
#define lson k<<1,l,mid
#define ll long long
#define rson k<<1|1,mid+1,r
using namespace std;
int n,m,pr[M*5],h[M*2],cnt,ct,siz[M],son[M],fa[M],dep[M],topf[M],id[M],sf[M];
ll sum[M*5],co[M*5],res;
inline int gi(){
int re=0,f=1;
char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')f=0,c=getchar();
while(c>='0'&&c<='9')re=re*10+c-'0',c=getchar();
return f?re:-re;
}
struct ee{
int t,nxt;
}e[M*2];
struct bitree{
ll a[M<<1];
void add(int x,int k){
while(x<=n){
a[x]+=k;
x+=x&(-x);
}
}
ll sum(int x){
ll re=0;
while(x>0){
re+=a[x];
x-=x&(-x);
}
return re;
}
}B1;
ll gcd(int a,int b){
return b?gcd(b,a%b):a;
}
void add(int fr,int t){
e[++ct].t=t;
e[ct].nxt=h[fr];
h[fr]=ct;
}
void dfs1(int u,int ff,int dp){
dep[u]=dp;
siz[u]=1;
fa[u]=ff;
for(int i=h[u];i;i=e[i].nxt){
int v=e[i].t;
if(v!=ff){
dfs1(v,u,dp+1);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int top){
++cnt;
id[u]=cnt;
topf[u]=top;
sf[cnt]=pr[u];
if(!son[u])return;
dfs2(son[u],top);
for(int i=h[u];i;i=e[i].nxt){
int v=e[i].t;
if(v!=fa[u]&&v!=son[u]){
dfs2(v,v);
}
}
}
void built(int k,int l,int r){
if(l==r){
co[k]=sf[l];
return;
}
built(lson);
built(rson);
co[k]=gcd(co[k<<1],co[k<<1|1]);
}
void upd(int k,int l,int r,int L,int R,int c){
if(l>=L&&r<=R){
co[k]+=c;
return;
}
if(L<=mid)//***
upd(lson,L,R,c);
if(R>mid)//***
upd(rson,L,R,c);
co[k]=gcd(co[k<<1],co[k<<1|1]);
}
void wk1(int a,int b,int c){
while(topf[a]!=topf[b]){
if(dep[topf[a]]>dep[topf[b]])
swap(a,b);
B1.add(id[topf[b]],c);
B1.add(id[b]+1,-c);
upd(1,1,n,id[topf[b]],id[topf[b]],c);
upd(1,1,n,id[b]+1,id[b]+1,-c);
b=fa[topf[b]];
}
if(dep[a]>dep[b])swap(a,b);
B1.add(id[a],c);
B1.add(id[b]+1,-c);
upd(1,1,n,id[a],id[a],c);
if(id[b]!=n)upd(1,1,n,id[b]+1,id[b]+1,-c);
}
ll query(int k,int l,int r,int L,int R){
ll re=0;
if(l>=L&&r<=R){
return co[k];
}
if(L<=mid)//***
re=gcd(re,query(lson,L,R));
if(R>mid)//***
re=gcd(re,query(rson,L,R));
return re;
}
void wk2(int a,int b){
res=0;
ll re=0;
// cout<<"2!"<<a<<" "<<b<<endl;
while(topf[a]!=topf[b]){
if(dep[topf[a]]>dep[topf[b]])
swap(a,b);
res=abs(gcd(B1.sum(id[topf[b]]),query(1,1,n,id[topf[b]]+1,id[b])));
re=gcd(re,res);
b=fa[topf[b]];
}
if(dep[a]>dep[b])swap(a,b);
res=abs(gcd(B1.sum(id[a]),query(1,1,n,id[a]+1,id[b])));
re=gcd(re,res);
printf("%lld
",re);
}
int main(){
n=gi();
for(int i=1;i<n;i++){
int u=gi()+1,v=gi()+1;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++){
scanf("%d",&pr[i]);
// B1.add(i,pr[i]-pr[i-1]);
}
m=gi();
dfs1(1,0,1);
dfs2(1,1);
for(int i=n;i;i--){
sf[i]-=sf[i-1];
B1.add(i,sf[i]);
}
built(1,1,n);
char op[2];
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='C'){
int a,b,c;
a=gi()+1;b=gi()+1;c=gi();
wk1(a,b,c);
}else{
int a,b;
a=gi()+1;b=gi()+1;
wk2(a,b);
}
}
return 0;
}
质因数分解
void Solve(LL n)
02.{
03. p.clear();
04. for(LL i=2; i*i<=n; i++)
05. {
06. if(n%i==0)
07. {
08. p.push_back(i);
09. while(n%i==0) n/=i;
10. }
11. }
12. if(n>1)
13. p.push_back(n); //这个不可以缺少
14.}
SG 函数
//f[]:可以取走的石子个数
//sg[]:0~n的SG函数值
int f[maxn],sg[maxn],mex[maxn];
void getSG(int n){
int i,j;
memset(sg,0,sizeof(sg));
for(i=1;i<=n;i++){
memset(mex,0,sizeof(mex));
for(j=1;f[j]<=i&&f[j]<=m;j++) //注意加f[i]的限定条件,此处为f[j]<=m
mex[sg[i-f[j]]]=1;
for(j=0;j<=n;j++){ //求mex中未出现的最小的非负整数
if(mex[j]==0){
sg[i]=j;
break;
}
}
//cout<<i<<" "<<sg[i]<<endl;
}
}
数位DP
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
typedef long double ld;
typedef long long ll;
const int inf = 1e9 + 7;
const int mod = 1e9 + 7;
const int MAX_N = 2e1 + 7;
using namespace std;
ll dp[MAX_N][2][2][2][2];
int a[MAX_N];
int len;
ll dfs(int pos, int ans, int has0, int has1, int has2, int lead, int limit)
{
if(!pos) return ans;
if(dp[pos][ans][has0][has1][has2] != -1 && !lead && !limit) return dp[pos][ans][has0][has1][has2];
ll res = 0; //暂时记录当前方案数
int up = limit ? a[pos] : 9; //up为当前位能取到的最大值
for(int i=0;i<=up;i++) {
int dhas0 = 0, dhas1 = 0, dhas2 = 0, dans = 0;
if(i%3 == 0) dhas0 = 1;
if(i%3 == 1) dhas1 = 1;
if(i%3 == 2) dhas2 = 1;
if(has1) {
if((1+i)%3 == 0) dhas0 = 1;
if((1+i)%3 == 1) dhas1 = 1;
if((1+i)%3 == 2) dhas2 = 1;
}
if(has2) {
if((2+i)%3 == 0) dhas0 = 1;
if((2+i)%3 == 1) dhas1 = 1;
if((2+i)%3 == 2) dhas2 = 1;
}
if(dhas0 && (!lead || lead && i)) dans = 1;
res += dfs(pos-1, ans||dans, dhas0, dhas1, dhas2, !i && lead, i==up&&limit); //当前位为前导0
//printf("(%d,%d, %d%d%d%d)", pos, i, dans, dhas0, dhas1, dhas2);
}
if(!lead && !limit) dp[pos][ans][has0][has1][has2] = res;
return res;
}
ll solve(ll x)
{
len = 0;
while(x) {
a[++len] = x%10;
x /= 10;
}
memset(dp, -1, sizeof(dp));
return dfs(len, 0, 1, 0, 0, 1, 1);
}
int main()
{
int T;
cin>>T;
while(T--) {
ll l, r;
cin>>l>>r;
cout<<solve(r)-solve(l-1)<<endl;
}
}
欧拉路 欧拉回路
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1005;
int n, m, flag, top, sum, du[N], ans[5005], map[N][N];
void dfs(int x)
{
ans[++top] = x;
for(int i = 1; i <= n; i++)
{
if(map[x][i] >= 1)
{
map[x][i]--;
map[i][x]--;
dfs(i);
break;
}
}
}
void fleury(int x)
{
top = 1;
ans[top] = x;
while(top > 0)
{
int k = 0;
for(int i = 1; i <= n; i++)//判断是否可扩展
{
if(map[ans[top]][i] >= 1)//若存在一条从ans[top]出发的边 那么就是可扩展
{k = 1; break;}
}
if(k == 0)//该点x没有其他的边可以先走了(即不可扩展), 那么就输出它
{
printf("%d ", ans[top]);
top--;
}
else if(k == 1)//如可扩展, 则dfs可扩展的哪条路线
{
top--;//这需要注意
dfs(ans[top+1]);
}
}
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
memset(du, 0, sizeof(du));
memset(map, 0, sizeof(map));
for(int i = 1; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
map[x][y]++; //记录边, 因为是无向图所以加两条边, 两个点之间可能有多条边
map[y][x]++;
du[x]++;
du[y]++;
}
flag = 1; // flag标记开始点。 如果所有点度数全为偶数那就从1开始搜
sum = 0;
for(int i = 1; i <= n; i++)
{
if(du[i] % 2 == 1)
{
sum++;
flag = i;// 若有奇数边, 从奇数边开始搜
}
}
if(sum == 0 || sum == 2)
fleury(flag);
}
return 0;
}
#include <bits/stdc++.h> //欧拉回路
using namespace std;
const int N = 1e5 + 5;
const int M = 1e5 + 5;
stack<int> stk;
struct edge {
int x, y;
}e[M * 2];
int n, m, cnt;
bool vis[M * 2];
int head[N], nxt[M * 2];
void add(int x, int y) {//连边
cnt ++;
e[cnt].x = x;
e[cnt].y = y;
nxt[cnt] = head[x];
head[x] = cnt;
}
void dfs(int x) {
for(int i = head[x]; i; i = nxt[i]) {
if(!vis[i]) {
vis[i] = 1;
dfs(e[i].y);
stk.push(e[i].y);
}
}
}
int main() {
cin >> n >> m;
for(int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
add(u, v);
add(v, u);
}
dfs(1);
stk.push(1);
while(!stk.empty()) {
printf("%d
",stk.top());
stk.pop();
}
return 0;
}
Kosaraju
#define reset(a) memset((a),0,sizeof((a)))
using namespace std;
static char buf[100000],*pa,*pd;
const int N=4001000;
struct edge{
int to,next;
}e[N];
int head[N],tot,HEAD[N];
int n,m,cnt,turn[N],belong[N],vis[N];
void add(int x,int y){
e[++tot].to=y;e[tot].next=head[x];head[x]=tot;
e[++tot].to=x;e[tot].next=HEAD[y];HEAD[y]=tot;
}
void dfs1(int u){
int i;
vis[u]=1;
for(i=head[u];i;i=e[i].next)
if(!vis[e[i].to])
dfs1(e[i].to);
turn[++cnt]=u;
}
void dfs2(int u){
belong[u]=cnt;vis[u]=1;
for(int i=HEAD[u];i;i=e[i].next)
if(!vis[e[i].to])
dfs2(e[i].to);
}
void kosaraju(){
for(int i=1;i<=2*n;i++)
if(!vis[i])dfs1(i);
reset(vis);cnt=0;
for(int i=2*n;i>=1;i--)
if(!vis[turn[i]])
cnt++,dfs2(turn[i]);
}
int main(){
n=read();m=read();
register int i,x,y,f1,f2;
for(i=1;i<=m;i++){
x=read();f1=read();y=read();f2=read();
add(x+n*(f1&1),y+n*(f2^1));
add(y+n*(f2&1),x+n*(f1^1));
}
kosaraju();
for(i=1;i<=n;i++)
if(belong[i]==belong[i+n]){
cout<<"IMPOSSIBLE";return 0;
}
cout<<"POSSIBLE
";
for(i=1;i<=n;i++){
cout<<(belong[i]>belong[i+n])<<' ';
}
return 0;
}