文章目录

  • 基础算法
    • 二分
    • 高精度
    • java大数
    • 归并排序
    • 第k小数
    • 三分
    • 数组模拟双向链表
    • 快读
    • 计算程序运行时间
    • STL离散化
  • 数学
    • gcd
    • 扩展欧几里得
    • 容斥原理
    • 卡特兰数
    • 组合数
    • 中国剩余定理
    • 素数筛
    • 逆元
    • 质因数分解
  • 数据结构
    • ST表
    • 优先队列
    • 树状数组
    • 单调栈
    • 线段树
    • 主席树
    • 树上倍增求LCA
    • 树链剖分
    • 莫队
  • 字符串
    • 字典树
    • 字符串hash
  • 图论
    • 图的连通子图

基础算法

二分

int bisearch(int l, int r,int x)
{while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid + 1;}return l;
}

高精度

//加法
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;vector<int> add(vector<int> &A, vector<int> &B)
{vector<int> C;int t = 0; //进位for (int i = 0; i < A.size() || i < B.size(); i++){if (i < A.size())t += A[i];if (i < B.size())t += B[i];C.push_back(t % 10);t /= 10;}if (t)C.push_back(1);return C;
}
int main()
{string a, b;int t;cin >> t;for (int o = 1; o <= t; o++){vector<int> A, B;cin >> a >> b; //a="123456"for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0'); //A=[6,5,4,3,2,1]for (int i = b.size() - 1; i >= 0; i--)B.push_back(b[i] - '0');auto C = add(A, B); //c++11标准,for循环可以范围遍历;一个变量冒号一个list或容器。cout<<"Case "<<o<<":"<<endl;cout<<a<<" + "<<b<<" = ";for (int i = C.size() - 1; i >= 0; i--)printf("%d", C[i]); //个位数先放进去}cout<<endl;if(o!=t)cout<<endl;}
}

java大数

import java.util.Scanner;
import java.math.*;public class Main
{public static void main(String[] args) {Scanner cin = new Scanner(System.in);int t,i=1;t=cin.nextInt();while(i<=t){i++;BigInteger n,n1,k,bottom;   n=cin.nextBigInteger();BigInteger s1=new BigInteger("1");//1BigInteger s2=new BigInteger("2");//2BigInteger mods=new BigInteger("1000000007");n1=n.add(s1);//n+1BigInteger sss;BigInteger s12=new BigInteger("12");//12BigInteger nd2;//(n+1)^2nd2=n1.pow(2);BigInteger nd21;//(n+1)^2-1nd21=nd2.subtract(s1);//k=nd2.multiply(nd21);k=k.divide(s12);bottom=n.multiply(n1);BigInteger bottom1,n2n1;bottom1=n.multiply(n1);n2n1=n.multiply(s2);n2n1=n2n1.add(s1);bottom1=bottom1.multiply(n2n1);bottom=bottom.multiply(bottom1);bottom=bottom.divide(s12);//System.out.println(bottom);BigInteger ans;ans=bottom;BigInteger s;s=n.multiply(n1);s=s.divide(s2);s=s.subtract(s1);BigInteger ans2,ks;ks=k.multiply(s);ans=ans.add(ks);System.out.println(ans.mod(mods));ans2=n.pow(2);ans2=ans2.multiply(bottom);System.out.println(ans2.mod(mods));}}
}

归并排序

void merge_sort(int start,int end){if(start>=end){return;}int start1=start,end1=(start+end)/2,start2=end1+1,end2=end;merge_sort(start1,end1);merge_sort(start2,end2);int k=start;while(start1<=end1&&start2<=end2){arr[k++]=a[start1]<a[start2]?a[start1++]:a[start2++];}while(start1<=end1){arr[k++]=a[start1++];}while(start2<=end2){arr[k++]=a[start2++];}for(int i=start;i<=end;i++){a[i]=arr[i];}
}

第k小数

#include <bits/stdc++.h>using namespace std;
#define ll long long
const int maxn = 5e6 + 10;inline int read()
{int x = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-')f = -1;ch = getchar();}while (ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar();}return x * f;
}int q[maxn];
int quick_sort(int q[], int l, int r, int k)
{if (l >= r)return q[l];int i = l - 1, j = r + 1, x = q[l + r >> 1];while (i < j){doi++;while (q[i] < x);doj--;while (q[j] > x);if (i < j)swap(q[i], q[j]);}if (j - l + 1 >= k)return quick_sort(q, l, j, k);elsereturn quick_sort(q, j + 1, r, k - (j - l + 1));
}
int main()
{int n, k;int t;cin >> t;while (t--){//scanf("%d%d", &n, &k);n=read();k=read();for (int i = 0; i < n; i++)q[i]=read();cout << quick_sort(q, 0, n - 1, k) << endl;}
}

三分

int three_fen(int l,int r)
{while(l<r){int m1=(2*l+r)/3;int m2=(2*r+l+2)/3;if(calc(m1)<=calc(m2))r=m2-1;else{l=m1+1;}}return l;
}

数组模拟双向链表

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int N=10000015,mod=1e9+7;
template<typename T>
void Debug(T x,string s){cout<<s<<": "<<x<<endl;
}
struct node
{int val,p_cnt;int next,last;
}a[N];#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
int vis[N],vis_p[N];//value值在链表中的位置,value值对应的数组下标
struct linklist
{int head=1,tail=1,sz=0,mid=tail;void insertl(int tot){sz++;if(sz==1){head=tail=tot;vis_p[tot]=0;a[tot].last=-1;a[tot].next=-1;mid=tail;}else{a[tot].next=head;a[tot].last=-1;a[head].last=tot;vis_p[tot]=vis_p[head]-1;head=tot;if(sz%2==1){movel();}else{mid=mid;}}}void insertr(int tot){sz++;if(sz==1){head=tail=tot;vis_p[tot]=0;a[tot].last=-1;a[tot].next=-1;mid=tot;}else{a[tot].last=tail;a[tot].next=-1;a[tail].next=tot;vis_p[tot]=vis_p[tail]+1;tail=tot;if(sz%2==0){mover();}else mid=mid;}}void del(int tot){int tl=a[tot].last,tr=a[tot].next;if(tr!=-1)a[tl].next=tr;if(tl!=-1)a[tr].last=tl;if(tot==head){    head=a[head].next;}if(tot==tail){tail=a[tail].last;}if(vis_p[mid]>vis_p[tot]){if(sz%2==1) mover();else mid=mid;}else if(vis_p[mid]<vis_p[tot]){if(sz%2==0) movel();else mid=mid;}else if(mid==tot){if(sz%2==0) movel();else mover();}sz--;a[tot].last=a[tot].next=-1;}void movel(){mid=a[mid].last;}void mover(){mid=a[mid].next;}
}List;
int tot=0;
void solve()
{int posl=0,posr=0;a[0].last=a[0].next=-1;int q;scanf("%d ",&q);char c;for(int i=1;i<=q;i++){scanf("%c ",&c);// cout<<c<<endl;if(c=='L'){++tot;List.insertl(tot);}else if(c=='R'){++tot;List.insertr(tot);}else if(c=='G'){int x;scanf("%d ",&x);List.del(x);}else{printf("%d\n",List.mid);}}
}
int main()
{#ifndef ONLINE_JUDGEfreopen("b.txt", "r", stdin);freopen("bout.txt", "w", stdout);
#endif
// #ifndef ONLINE_JUDGE
//  freopen("a.txt", "r", stdin);
//  freopen("aout.txt", "w", stdout);
// #endifint t;t=1;while (t--)solve();
}

快读

template <typename _Tp>
inline _Tp read(_Tp &x) {char ch = getchar(), sgn = 0; x = 0;while (ch ^ '-' && !isdigit(ch)) ch = getchar();if (ch == '-') ch = getchar(), sgn = 1;while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();if (sgn) x = -x;return x;
}
int main() {b = read(a);
}
//可读int, long long  short

计算程序运行时间

cerr << "Time execute: " << clock() / (double)CLOCKS_PER_SEC << " sec" << endl;

STL离散化

sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());

数学

gcd

int gcd(int a,int b)
{return b?gcd(b,a%b):a;
}

扩展欧几里得

#include<iostream>
#include<cstdio>
#include<cmath>using namespace std;int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法
{if(b==0){x=1;y=0;return a;  //到达递归边界开始向上一层返回}int r=exgcd(b,a%b,x,y);int temp=y;    //把x y变成上一层的y=x-(a/b)*y;x=temp;return r;     //得到a b的最大公因数
}

容斥原理

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int Maxn = 20;
int Number[Maxn + 5];
ll N, M, Tot;
ll Ans = 0;
bool is_prime(int x)
{for(int i=2;i*i<=x;i++){if(x%i==0) return false;}return true;
}
ll Gcd(ll A, ll B){return !B ? A : Gcd(B, A % B);
}
void Dfs(ll Cur, ll Cnt, ll Limit, ll LCM){if (Cnt == Limit) {if (Limit & 1) {Ans += (N - 1) / LCM;}else {Ans -= (N - 1) / LCM;}return;}if (Cur >= Tot) {return ;}ll NowLCM = LCM == -1 ? Number[Cur] : LCM;Dfs(Cur + 1, Cnt + 1, Limit, Number[Cur] / Gcd(NowLCM, Number[Cur]) * NowLCM);Dfs(Cur + 1, Cnt, Limit, LCM);
}
int main()
{#ifndef ONLINE_JUDGEfreopen("a.txt","r",stdin);freopen("aout.txt","w",stdout);
#endifint tot=0;// Number[]=2;for(int i=2;i<=100;i++){if(is_prime(i)){Number[++tot]=i;}if(tot>17) break;}int t;cin>>t;while (t--) {cin>>N>>M;Tot = 1;Ans = 0;Tot=M+1;for (int i = 1; i < Tot; i++) {Dfs(1, 0, i, -1);} printf("%lld\n", N-Ans-1);}
}

卡特兰数

#include<cstdio>
#include<cstring>
#define N 60
using namespace std;
int main()
{int h[101][2*N+1],i,j,k,l,n;memset(h,0,sizeof(h));h[0][1]=1;h[1][1]=1;for(i=2;i<=100;i++){for(j=0;j<i;j++)for(k=1;k<N;k++)for(l=1;l<N;l++)h[i][k+l-1]+=h[j][k]*h[i-j-1][l];for(j=1;j<N;j++){h[i][j+1]+=h[i][j]/10;h[i][j]%=10;}}while(scanf("%d",&n)!=EOF){i=N;while(h[n][--i]==0);for(j=i;j>0;j--)printf("%d",h[n][j]);printf("\n");}return 0;
}

组合数

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=2*150007;
const ll mod=998244353;ll quick_mod(ll a, ll b)
{ll ans = 1;a %= mod;while(b){if(b & 1){ans = ans * a % mod;b--;}b >>= 1;a = a * a % mod;}return ans;
}ll C(ll n, ll m)
{if(m > n) return 0;ll ans = 1;for(int i=1; i<=m; i++){ll a = (n + i - m) % mod;ll b = i % mod;ans = ans * (a * quick_mod(b, mod-2) % mod) % mod;}return ans;
}ll Lucas(ll n, ll m)
{if(m == 0) return 1;return C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod;
}
//递推公式
const int N = 1e6 + 7, mod = 1e9 + 7;
int n, m, k, t;
int inv[N];
int fact[N], infact[N];void init (int n)
{fact[0] = infact[0] = inv[0] = inv[1] = 1;for (int i = 2; i <= n; ++ i) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;for (int i = 1; i <= n; ++ i) {fact[i] = 1ll * fact[i - 1] * i % mod;infact[i] = 1ll * infact[i - 1] * inv[i] % mod;}
}int C(int n, int m)
{if(n < m) return 0;if(m == 0 || n == m) return 1;return 1ll * fact[n] * infact[m] % mod * infact[n - m] % mod;
}

中国剩余定理

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;//扩展欧几里得,ax+by=gcd(a,b)
ll e_gcd(ll a,ll b,ll &x,ll &y){if(b==0){x=1,y=0;return a;}ll res=e_gcd(b,a%b,y,x);y-=(a/b)*x;return res;
}//中国剩余定理,pri[]存放互质的数,r[]存放余数,n为个数
ll china(ll pri[],ll r[],ll n){ll M=1,m,d,res=0;for(int i=0;i<n;i++) M*=pri[i]; //最小公倍数for(int i=0;i<n;i++){m=M/pri[i]; //m为除当前这个数不能整除以外都能够被其他数整除,就是其他数的最小公倍数ll x,y;d=e_gcd(pri[i],m,x,y); // pri[i]*x+m*y=gcd(pri[i],m]res=(res+y*m*r[i])%M; } return (res%M+M)%M;  //满足的最小解
}ll pri[20],r[20];
int main(){int n;while(~scanf("%d",&n)){for(int i=0;i<n;i++)scanf("%lld %lld",&pri[i],&r[i]);ll ans=china(pri,r,n);printf("%lld\n",ans);}
} 

素数筛

  • 欧拉筛
#include<bits/stdc++.h>using namespace std;const int maxn=1e6;//这个是在哪一个范围内
int prime[maxn];
int visit[maxn];//1代表是偶数,0代表是奇数
void Prime()
{memset(visit,0,sizeof(visit));memset(prime,0,sizeof(visit));visit[1]=1;for (int i = 2;i <= maxn; i++) {if (!visit[i]) {prime[++prime[0]] = i;     }for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++) {visit[i*prime[j]] = 1;if (i % prime[j] == 0) {break;}}}
}
  • 欧拉筛质因数个数
for(int i=2;i<=10000000;i++)
{if(!f[i])prm[++cnt]=i,num[i]=1;for(int j=1;j<=cnt && i*prm[j]<=10000000;j++){f[i*prm[j]]=true;num[i*prm[j]]=num[i]+1;if(i%prm[j]==0)break;}
}
  • 欧拉函数
void euler()
{for (int i = 1; i <N; i++)a[i] = i;for (int i = 2; i <N; i += 2)a[i] /= 2;for (int i = 3; i <N; i += 2){if (a[i] == i)for (int j = i; j <N; j += i){if (j % i == 0)a[j] = a[j] - a[j] / i;}}a[0]=0;for(int i=1;i<N;i++){a[i]=a[i-1]+a[i];}
}
  • 欧拉降幂
#include<iostream>
using namespace std;
typedef long long ll;
ll read(string s,ll mod){ll x=0;for(int i=0;i<s.length();i++)x=((x<<3)+(x<<1)+(s[i]^48))%mod;return (x+mod-1)%mod;
}
ll pow(ll s,ll n,ll mod){ll sum=1;while(n){if(n&1)sum=sum*s%mod;s=s*s%mod;n>>=1;}return sum;
}
ll phi(ll x){ll t=x;for(int i=2;i<=x/i;i++)if(x%i==0){while(x%i==0)x/=i;t=t*(i-1)/i;}if(x>1)t=t*(x-1)/x;return t;
}
int main(){ ll x,mod,n;string nn;cin>>x>>nn>>mod;if(x==0){if(nn=="1")cout<<1%mod;else cout<<"0";return 0;}x%=mod;n=read(nn,phi(mod));cout<<pow(x%mod,n,mod);
}

逆元

void init(){fac[0] = 1;for(int i=1;i<=MN;i++)fac[i] = (ll)fac[i-1]*i%mod;inv[MN] = qpow(fac[MN],mod-2);for(int i=MN-1;i>=0;i--)inv[i] = (ll)inv[i+1]*(i+1)%mod;
}int C(int n,int m){if(m>n) return 0;return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
}ll pow_mod(ll a, ll b, ll p){//a的b次方求余pll ret = 1;while(b){if(b & 1) ret = (ret * a) % p;a = (a * a) % p;b >>= 1;}return ret;
}
ll Fermat(ll a, ll p){//费马求a关于b的逆元return pow_mod(a, p-2, p);
}

质因数分解

bool vis[N];
ll prime[N];
int cnt=0;
void primes()
{for(int i=2;i<=N;i++){if(vis[i]) {continue;}prime[++cnt]=i;for(int j=1;j<=N/i;j++){vis[i*j]=1;}}
}ll getprimefactor(long long n)
{ll ans=0;if(n==1){return 0;}if(!vis[N]){return 1;}for(int i=1;i<=cnt&&prime[i]*prime[i]<=n;i++){while(n%prime[i]==0){ans++;n/=prime[i];}}if(n>1){return ans+1;}return ans;
}

数据结构

ST表

void ST_init()
{for(int i=1;i<=N;++i)ST[i][0]=a[i];for(int j=1;j<30;++j){for(int i=1;i<=N;++i){if(i+(1<<j)-1>N) break;ST[i][j]=__gcd(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);}}
}long long ST_query(int s,int e)
{int k=(int)((log(e-s+1.0)/log(2.0)));return __gcd(ST[s][k],ST[e-(1<<k)+1][k]);
}void ST_preowrk()
{for(int i=1;i<=n;i++) f[i][0]=a[i];int t=log(n)/log(2)+1;for(int j=1;j<t;j++){for(int i=1;i<=n-(1<<j)+1;i++){f[i][j]=max(f[i][j-1],f[i+1<<(j-1)][j-1]);}}
}ll ST_query(int l,int r)
{int k=log(r-l+1)/log(2);return max(f[l][k],f[r-(1<<k)+1][k]);
}

优先队列

#include <iostream>
#include <queue>
using namespace std;
int main()
{int n;while(cin>>n){int i,k,j,t1;long long sum=0;priority_queue<int,vector<int>,greater<int> > p;for(i=0;i<n;i++){cin>>k;p.push(k);}while(p.size()!=1){t1=p.top();p.pop();t1+=p.top();sum+=t1;p.pop();p.push(t1);}cout<<sum<<endl;}
}

树状数组

//树状数组模板
int sum[N];
int lowbit(int x)
{return x & (-x);
}
void add(int x, int num)
{while (x <= n){sum[x] += num;x += lowbit(x);}
}
int ask(int x)
{int res = 0;while (x > 0){res += sum[x];x -= lowbit(x);}return res;
}

单调栈

int tot=0;
h[m+1]=0;
for(int j=1;j<=m+1;j++){while(tot&&h[que[tot]]>h[j]){ans=max(ans,(j-1-que[tot-1])[que[tot]]);//这里可以理解为以 h[que[tot]]个高度可以向左向右拓展的面积。tot--;}que[++tot]=j;
}

线段树

  • 单点修改,区间查询
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100005;
const int INF = 0x3f3f3f3f;
int s[N << 2] ,lc[N << 2] ,rc[N << 2];
int n,m,num[N];
void build(int u ,int l ,int r) {lc[u] = l;rc[u] = r;if(l == r) {s[u] = num[l];return ;}int mid = (l + r) / 2;build(u * 2 , l , mid);build(u * 2 + 1 , mid + 1 ,r);s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
void change(int u , int x , int v) {if(lc[u] == x && rc[u] == x) {s[u] = v;return ;}int mid = (lc[u] + rc[u]) / 2;if(x <= mid)change(u * 2 , x , v);elsechange(u * 2 + 1 , x , v);s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
int query(int u , int l ,int r) {int res = INF;if(l <= lc[u] && r >= rc[u]) {return s[u];}int mid = (lc[u] + rc[u]) / 2;if(l <= mid) res = min(res , query(u * 2 , l , r));if(r > mid) res = min(res , query(u * 2 + 1 , l , r));return res;
}
  • 区间操作lowbit
#include<bits/stdc++.h>using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&(-x))
const ll mod = 998244353;
ll powmod(ll a,ll b)
{ll res=1;a%=mod;while(b){if(b&1){res=res*a%mod;}a=a*a%mod;b>>=1;}return res;
}const int N = 1e5+50;
int n,m;
struct node
{int l,r;ll x,sum;int lazy;int flag;
}tree[N<<2];void push_up(int p)
{tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%mod;tree[p].flag=(tree[p<<1].flag&tree[p<<1|1].flag);
}void push_down(int p)
{if(tree[p].lazy==0) return;tree[p<<1].lazy+=tree[p].lazy;tree[p<<1|1].lazy+=tree[p].lazy;tree[p<<1].sum=(tree[p<<1].sum*powmod(2,tree[p].lazy))%mod;tree[p<<1|1].sum=(tree[p<<1|1].sum*powmod(2,tree[p].lazy))%mod;tree[p].lazy=0;
}void build_tree(int l,int r,int p)
{tree[p].l=l,tree[p].r=r;tree[p].lazy=tree[p].flag=0;if(l==r){scanf("%lld",&tree[p].x);tree[p].sum=tree[p].x;if(lowbit(tree[p].x)==tree[p].x) tree[p].flag=1;return;}int mid=l+r>>1;build_tree(l,mid,p<<1);build_tree(mid+1,r,p<<1|1);push_up(p);
}void update_tree(int l,int r,int p)
{if(l<=tree[p].l&&tree[p].r<=r&&tree[p].flag){tree[p].sum=(tree[p].sum*2)%mod;tree[p].lazy++;return;}if(tree[p].l==tree[p].r){tree[p].x=tree[p].sum=tree[p].sum+lowbit(tree[p].sum);if(lowbit(tree[p].x)==tree[p].x){tree[p].flag=1;}return;}push_down(p);int mid=(tree[p].l+tree[p].r)>>1;if(l<=mid) update_tree(l,r,p<<1);if(mid<r) update_tree(l,r,p<<1|1);push_up(p);
}ll ask_sum(int l,int r,int p)
{if(l<=tree[p].l&&tree[p].r<=r){return tree[p].sum;}ll res=0;push_down(p);int mid=(tree[p].l+tree[p].r)>>1;if(l<=mid) {res=(res+ask_sum(l,r,p<<1))%mod;}if(mid<r){res=(res+ask_sum(l,r,p<<1|1))%mod;}return res;
}void solve()
{scanf("%d",&n);build_tree(1,n,1);scanf("%d",&m);int op,l,r;for(int i=1;i<=m;i++){scanf("%d%d%d",&op,&l,&r);if(op==1){update_tree(l,r,1);}else{printf("%lld\n",ask_sum(l,r,1));}}
}int main()
{int t;scanf("%d",&t);while(t--){solve();}
}
  • 区间修改,区间查询
#include<bits/stdc++.h>using namespace std;const int maxn=100010;int a[maxn+2];struct tree{int l,r;long long pre,add;
}t[4*maxn+2];void bulid(int p,int l,int r){t[p].l=l;t[p].r=r;if(l==r){t[p].pre=a[l];return;}int mid=l+r>>1;bulid(p*2,l,mid);bulid(p*2+1,mid+1,r);t[p].pre=t[p*2].pre+t[p*2+1].pre;
} void spread(int p){if(t[p].add){t[p*2].pre+=t[p].add*(t[p*2].r-t[p*2].l+1);t[p*2+1].pre+=t[p].add*(t[p*2+1].r-t[p*2+1].l+1);t[p*2].add+=t[p].add;t[p*2+1].add+=t[p].add;t[p].add=0;}
}void change(int p,int x,int y,int z){if(x<=t[p].l && y>=t[p].r){t[p].pre+=(long long)z*(t[p].r-t[p].l+1);t[p].add+=z;return;}spread(p);int mid=t[p].l+t[p].r>>1;if(x<=mid) change(p*2,x,y,z);if(y>mid) change(p*2+1,x,y,z);t[p].pre=t[p*2].pre+t[p*2+1].pre;
}long long ask(int p,int x,int y){if(x<=t[p].l && y>=t[p].r) return t[p].pre;spread(p);int mid=t[p].l+t[p].r>>1;long long ans=0;if(x<=mid) ans+=ask(p*2,x,y);if(y>mid) ans+=ask(p*2+1,x,y);return ans;
}int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);bulid(1,1,n);for(int i=1;i<=m;i++){int q,x,y,z;scanf("%d",&q);if(q==1){scanf("%d%d%d",&x,&y,&z);change(1,x,y,z);}else {scanf("%d%d",&x,&y);cout<<ask(1,x,y)<<endl;}}return 0;
}
//问最小值
//Q a b 询问(a,b)中最小值
//C a b 将a点值改为b
#include <bits/stdc++.h>
using namespace std;
#define maxn 200005int min(int a, int b)
{return a>b ? b : a;
}
int tree[4 * maxn];void pushup(int i)
{tree[i] = min(tree[i << 1], tree[i << 1 | 1]);
}void build(int i, int l, int r)
{if (l == r){scanf("%lld", &tree[i]);return;}int mid = (l + r) / 2;build(i << 1, l, mid);build(i << 1 | 1, mid + 1, r);pushup(i);
}void update(int i, int l, int r, int x, int val)
{if (l == r)///l==x??±???{tree[i] = val;return;}int mid = (l + r) / 2;if (x <= mid) update(i << 1, l, mid, x, val);else update(i << 1 | 1, mid + 1, r, x, val);pushup(i);
}int query(int i, int l, int r, int x, int y)
{if (x <= l && r <= y)return tree[i];int minn = 9999999;int mid = (l + r) / 2;if (x <= mid) minn = min(minn, query(i << 1, l, mid, x, y));if (y>mid) minn = min(minn, query(i << 1 | 1, mid + 1, r, x, y));return minn;
}int main()
{int n, m;int b, c;char a;while (scanf("%d%d", &n, &m) != -1){build(1, 1, n);while (m--){scanf(" %c%d%d", &a, &b, &c);if (a == 'Q')printf("%d\n", query(1, 1, n, b, c));elseupdate(1, 1, n, b, c);}}return 0;
}#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
int tree[4 * maxn];void pushup(int i)
{tree[i] = max(tree[i << 1], tree[i << 1 | 1]);
}void build(int i, int l, int r)
{if (l == r){tree[i] = 0;return;}int mid = (l + r) / 2;build(i << 1, l, mid);build(i << 1 | 1, mid + 1, r);pushup(i);
}void update(int i, int l, int r, int x, int val)
{if (l == r){tree[i] = val;return;}int mid = (l + r) / 2;if (x <= mid) update(i << 1, l, mid, x, val);else update(i << 1 | 1, mid + 1, r, x, val);pushup(i);
}int query(int i, int l, int r, int x, int y)
{if (x <= l && r <= y)return tree[i];int maxm = 0;int mid = (l + r) / 2;if (x <= mid) maxm = max(maxm, query(i << 1, l, mid, x, y));if (y>mid) maxm = max(maxm, query(i << 1 | 1, mid + 1, r, x, y));return maxm;
}int main()
{int n, m;int b, c;char a;while (~scanf("%d%d", &n, &m)){build(1, 1, n);while (m--){scanf(" %c%d%d", &a, &b, &c);if (a == 'Q')printf("%d\n", query(1, 1, n, b, c));elseupdate(1, 1, n, b, c);}}
}

主席树

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5;  // 数据范围
int tot, n, m;
int sum[(maxn << 5) + 10], rt[maxn + 10], ls[(maxn << 5) + 10],rs[(maxn << 5) + 10];
int a[maxn + 10], ind[maxn + 10], len;
inline int getid(const int &val) {  // 离散化return lower_bound(ind + 1, ind + len + 1, val) - ind;
}
int build(int l, int r) {  // 建树int root = ++tot;if (l == r) return root;int mid = l + r >> 1;ls[root] = build(l, mid);rs[root] = build(mid + 1, r);return root;  // 返回该子树的根节点
}
int update(int k, int l, int r, int root) {  // 插入操作int dir = ++tot;ls[dir] = ls[root], rs[dir] = rs[root], sum[dir] = sum[root] + 1;if (l == r) return dir;int mid = l + r >> 1;if (k <= mid)ls[dir] = update(k, l, mid, ls[dir]);elsers[dir] = update(k, mid + 1, r, rs[dir]);return dir;
}
int query(int u, int v, int l, int r, int k) {  // 查询操作int mid = l + r >> 1,x = sum[ls[v]] - sum[ls[u]];  // 通过区间减法得到左儿子的信息if (l == r) return l;if (k <= x)  // 说明在左儿子中return query(ls[u], ls[v], l, mid, k);else  // 说明在右儿子中return query(rs[u], rs[v], mid + 1, r, k - x);
}
inline void init() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i) scanf("%d", a + i);memcpy(ind, a, sizeof ind);sort(ind + 1, ind + n + 1);len = unique(ind + 1, ind + n + 1) - ind - 1;rt[0] = build(1, len);for (int i = 1; i <= n; ++i) rt[i] = update(getid(a[i]), 1, len, rt[i - 1]);
}
int l, r, k;
inline void work() {while (m--) {scanf("%d%d%d", &l, &r, &k);printf("%d\n", ind[query(rt[l - 1], rt[r], 1, len, k)]);  // 回答询问}
}
int main() {init();work();return 0;
}
  • 查询前k大和
#include <bits/stdc++.h>using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 7;
int root[MAXN],n,q,size,num;//size 内存池的大小
ll a[MAXN],s[MAXN],b[MAXN];struct HJT_tree{int l,r,cnt;//cnt记录出现次数 sum记录和 val记录节点的值ll sum,val;
}tree[MAXN*40];void build(int &now,int l,int r){now = ++size;tree[now].cnt = tree[now].sum = tree[now].val = 0;if(l == r) return ;int mid = (l+r)>>1;build(tree[now].l,l,mid);build(tree[now].r,mid+1,r);
}void modify(int &now,int pre,int l,int r,int p,int val){tree[now = ++size] = tree[pre];tree[now].cnt++,tree[now].sum += val;if(l == r){tree[now].val = val;return ;}int mid = (l+r)>>1;if(p <= mid) modify(tree[now].l,tree[pre].l,l,mid,p,val);else modify(tree[now].r,tree[pre].r,mid+1,r,p,val);
}
//查前k大值,因为节点存的是值 所以找大的 应该先往右边找 看右边(也就是大的)的数量符合情况嘛
ll query(int now,int pre,int l,int r,int k){if(l == r) return tree[now].val * k;//因为一个值可能出现多次 那么计算答案的时候要把他们都算上int mid = (l+r)>>1;int tmp = tree[tree[now].r].cnt - tree[tree[pre].r].cnt;if(tmp >= k) return query(tree[now].r,tree[pre].r,mid+1,r,k);else return query(tree[now].l,tree[pre].l,l,mid,k-tmp) + tree[tree[now].r].sum - tree[tree[pre].r].sum;//注意左边的k要变成k-tmp的形式
}int getid(ll x){ return lower_bound(b+1,b+1+num,x)-b; }int main(){int T;scanf("%d",&T);while(T--){memset(root,0,sizeof(root));size = 0;scanf("%d",&n);for(int i = 1;i <= n;i ++){scanf("%lld",&a[i]);b[i] = a[i];s[i] = s[i-1] + (1ll*i*i);//这里i会爆 所以开ll}/*****离散化 + 初始化****/sort(b+1,b+1+n);num = unique(b+1,b+1+n)-b-1;build(root[0],1,num);/***********************/for(int i = 1;i <= n;i ++){int p = getid(a[i]);modify(root[i],root[i-1],1,num,p,a[i]);}scanf("%d",&q);int l,r,k;while(q--){scanf("%d%d%d",&l,&r,&k);ll ans = query(root[r],root[l-1],1,num,k);ans += s[r-l+1];printf("%lld\n",ans);}}return 0;
}

树上倍增求LCA

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1000010;
inline void read(int &n)
{char c=getchar();bool flag=0;n=0;while(c<'0'||c>'9')  c=='-'?flag=1,c=getchar():c=getchar();while(c>='0'&&c<='9')  n=n*10+c-48,c=getchar();flag==1?n=-n:n=n;
}
struct node
{int v,nxt;
}edge[MAXN];
int head[MAXN];
int num=1;
inline void add_edge(int x,int y)
{edge[num].v=y;edge[num].nxt=head[x];head[x]=num++;
}
int f[MAXN][21];
int deep[MAXN];
int n,m,root;
void dfs(int now)
{for(int i=head[now];i!=-1;i=edge[i].nxt)if(!deep[edge[i].v])deep[edge[i].v]=deep[now]+1,f[edge[i].v][0]=now,dfs(edge[i].v);
}
void PRE()
{for(int i=1;i<=19;i++)  for(int j=1;j<=n;j++)f[j][i]=f[f[j][i-1]][i-1];
}
int LCA(int x,int y)
{if(deep[x]<deep[y]) swap(x,y);//x是靠下的那个。for(int i=19;i>=0;i--)if(deep[f[x][i]]>=deep[y])x=f[x][i];if(x==y)  return x;for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return   f[x][0];
}
int main()
{memset(head,-1,sizeof(head));read(n);read(m);read(root);for(int i=1;i<=n-1;i++){int x,y;read(x);read(y);add_edge(x,y);add_edge(y,x);}deep[root]=1;dfs(root);PRE();for(int i=1;i<=m;i++){int x,y;read(x);read(y);printf("%d\n",LCA(x,y));}return 0;
}

树链剖分

void dfs1(int o) {son[o] = -1;siz[o] = 1;for (int j = h[o]; j; j = nxt[j])if (!dep[p[j]]) {dep[p[j]] = dep[o] + 1;fa[p[j]] = o;dfs1(p[j]);siz[o] += siz[p[j]];if (son[o] == -1 || siz[p[j]] > siz[son[o]]) son[o] = p[j];}
}
void dfs2(int o, int t) {top[o] = t;cnt++;dfn[o] = cnt;rnk[cnt] = o;if (son[o] == -1) return;dfs2(son[o], t);  // 优先对重儿子进行 DFS,可以保证同一条重链上的点 DFS 序连续for (int j = h[o]; j; j = nxt[j])if (p[j] != son[o] && p[j] != fa[o]) dfs2(p[j], p[j]);
}

莫队

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;const int maxn = 100010;int n,m,blo;
int l=1,r=0;
int c[maxn],cnt[maxn],pos[maxn];
ll res=0;struct Q{int l,r,id;
}q[maxn];
struct Ans{ll a,b;
}ans[maxn];bool cmp(Q a,Q b){if(pos[a.l]==pos[b.l]) return a.r<b.r;return a.l<b.l;
}void add(int i){res-=1ll*cnt[c[i]]*cnt[c[i]];++cnt[c[i]];res+=1ll*cnt[c[i]]*cnt[c[i]];
}void del(int i){res-=1ll*cnt[c[i]]*cnt[c[i]];--cnt[c[i]];res+=1ll*cnt[c[i]]*cnt[c[i]];
}ll gcd(ll a,ll b){if(a<b) swap(a,b); return b==0?a:gcd(b,a%b);
}ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }int main(){n=read(),m=read();blo=sqrt(n);for(int i=1;i<=n;i++) c[i]=read(),pos[i]=(i-1)/blo+1;for(int i=1;i<=m;i++){q[i].l=read(),q[i].r=read();q[i].id=i;}sort(q+1,q+1+m,cmp); for(int i=1;i<=m;i++){while(l<q[i].l){ del(l); l++; }while(l>q[i].l){ add(l-1); l--; }while(r<q[i].r){ add(r+1); r++; }while(r>q[i].r){ del(r); r--; }if(q[i].l==q[i].r){ans[q[i].id]=(Ans){0,1};continue;}ans[q[i].id]=(Ans){res-(r-l+1),1ll*(r-l+1)*(r-l)};}for(int i=1;i<=m;i++){ll g=gcd(ans[i].a,ans[i].b);printf("%lld/%lld\n",ans[i].a/g,ans[i].b/g); }return 0;
}

字符串

字典树

#include <bits/stdc++.h>using namespace std;#define PII pair<int,int>
typedef long long ll;
const int maxn = 1e3 + 7;
const int N = 4e6 + 7;
char mp[maxn][maxn];
char str[maxn],t[maxn];
int n,m;
int trie[N][26],idx,val[N];void insert(char *s,int x)
{int p = 0,len = strlen(s);for(int i = 0;i < len;i ++){int ch = s[i] - 'a';if(!trie[p][ch]) trie[p][ch] = ++idx;p = trie[p][ch];}val[p] = x;
}int query(char *s)
{int p = 0,len = strlen(s);for(int i = 0;i < len;i ++){int ch = s[i] - 'a';p = trie[p][ch];if(!p) return -1;}if(val[p]) return val[p];else return -1;
}void init()
{for(int i = 0;i <= idx;i ++){memset(trie[i],0,sizeof(trie[i]));val[i] = 0;}idx = 0;
}int main()
{int tt;scanf("%d",&tt);while(tt--){init();scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++){scanf("%s",mp[i]+1);}while(m--){int x;scanf("%s%d",str,&x);insert(str,x);}int flag = 0;ll sum = 0;for(int i = 1;i <= n;i++){for(int j = 1;j <= n;j++ ){int len = 0;if(mp[i][j] == '#') continue;while(mp[i][j] != '#' && j <= n){t[len++] = mp[i][j];j++;}t[len] = '\0';int ans = query(t);if(ans == -1) flag = 1;else sum += ans;}}for(int j=1;j<=n;j++){for(int i=1;i<=n;i++){int len = 0;if(mp[i][j] == '#') continue;while(mp[i][j] !='#'&& i <= n){t[len++] = mp[i][j];i++;}t[len] = '\0';int ans = query(t);if(ans == -1) flag = 1;else sum += ans;}}    if(flag) printf("-1\n");else printf("%lld\n",sum);               }
}

字符串hash

#include<iostream>
#include<algorithm>using namespace std;typedef unsigned long long ULL;
const int N=1e6+10,M=131;int n,m;
char str[N];ULL p[N],h[N];
ULL get(int l,int r)
{return h[r]-h[l-1]*p[r-l+1];
}int main()
{cin>>n>>m;cin>>str+1;p[0]=1;for(int i=1;i<=n;i++){h[i]=h[i-1]*M+str[i];p[i]=p[i-1]*M;}while(m--){int l1,r1,l2,r2;cin>>l1>>r1>>l2>>r2;if(get(l1,r1)==get(l2,r2)) puts("Yes");elseputs("No");}return 0;
}

图论

图的连通子图

#include<bits/stdc++.h>
const int N=1005;
using namespace std;
vector<int> t[N];
int vis[N]={0};
void dfs(int k)
{for(int i=0;i<t[k].size();i++){if(vis[t[k][i]]==0){   vis[t[k][i]]=1;dfs(t[k][i]);}}
}
int main()
{int n,m;//n个顶点,m条边 cin>>n>>m;int a,b;//边所连接的两个顶点for(int i=1;i<=m;i++){cin>>a>>b;t[a].push_back(b);t[b].push_back(a);}int ans=0;//记录连通块数量 for(int i=1;i<=n;i++){if(vis[i]==0){vis[i]=1;dfs(i);ans++; }      }cout<<ans<<endl;return 0;
}#include <bits/stdc++.h>using namespace std;
const int maxn = 3e5 + 3;
int edge[maxn][maxn];
vector<int> t[maxn];
int pre[maxn], root[maxn];void init(int nn)
{for (int i = 1; i <= nn; i++)pre[i] = i;
}
int find(int x)
{int f = x;while (x != pre[x]) //找到x的父节点x = pre[x];int j;while (f != pre[f]) //依次将x上面的节点的父节点赋为x;{j = f;f = pre[f];pre[j] = x;}return x;
}void merge(int a, int b)
{int t1, t2;t1 = find(a);t2 = find(b);if (t1 != t2){pre[t2] = t1;}
}int block(int nn)
{int ans = 0;for (int i = 1; i <= nn; i++)root[pre[i]] = 1;for (int i = 1; i <= nn; i++)ans += root[i];return ans;
}int main()
{int n, m;cin >> n >> m;init(n);for (int i = 1; i <= m; i++){int a,b;scanf("%d%d",&a,&b);t[a].push_back(b);t[b].push_back(a);// merge(a, b);}for (int i = 1; i <= n; i++){vector<int>::iterator it;for(it=t[i].begin();it!=t[i].size())printf("%d",block(n));}
}// void init(int nn)
// {//     for(int i=1;i<=nn;i++)
//     pre[i]=i;
// }
// int find(int x)
// {//     int f=x;
//     while(x!=pre[x])//找到x的父节点
//     x=pre[x];//     int j;
//     while(f!=pre[f])//依次将x上面的节点的父节点赋为x;
//     {//         j=f;
//         f= pre[f];
//         pre[j]=x;
//     }
//     return x;
// }// void merge(int a,int b)
//  {//      int t1,t2;
//      t1=find(a);
//      t2=find(b);
//      if(t1!=t2)
//      {//          pre[t2]=t1;
//      }
// }// int block(int nn)
// {//     int ans=0;
//     for(int i=1;i<=nn;i++)
//     root[pre[i]]=1;
//     for(int i=1;i<=nn;i++)
//     ans+=root[i];
//     return ans;
// }
// int main()
// {//     scanf("%d%d",&n,&m);
//     int a,b;//边所连接的两个顶点
//     init(n);
//     for(int i=1;i<=m;i++)
//     {//         scanf("%d%d",&a,&b);
//         t[a].push_back(b);
//         t[b].push_back(a);
//         merge(a,b);
//     }
//     printf("%d",block(n));
//     return 0;
// }

菜鸟ACM职业生涯模板总结相关推荐

  1. ACM Latex模板subsubsection换行

    ACM Latex模板subsubsection默认是不会换行的, 如果使用\\系统会报错. 其实可以用\ 来换行, 注意后面有一个空格. \subsubsection{section title}\ ...

  2. ACM数学模板1 高斯消元 Gaussian Elimination

    声明: 题目来源: https://www.luogu.com.cn/problem/P3389 https://www.luogu.com.cn/problem/P2447 https://ac.n ...

  3. acm算法模板(1)

    1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函数 10 1.6 面积 15 1.7 球面 16 1.8 三角形 17 1.9 三维几 ...

  4. ACM常用模板-数据结构

    数据结构方面常用模板总结,大多数代码摘自网络,个人整理总结 string: 任意进制转换:itoa(int n,char* s,int r) //将10进制n转换为r进制并赋给s流:#include& ...

  5. ACM算法模板总结(分类详细版)

    本文模均引用于y总的算法模板,网址:AcWing (转载请注明出处,本文属于持续更新ing.......biubiubiu......) 本人码风比起y总真的差远了,所以敲一遍后,还是想把y总的搬上来 ...

  6. Nobleman__ ACM 比赛模板 (C++ Java)个人总结 (不断更新) (自用)

    声明 : 本人刚学算法一年,都是自己做题常用的模板,不时总结下. 大致分为:乱七八糟, 数论,图论,动态规划,几何,Java 还有一些奇葩定理, 常用素数: 1 e 8 左 右 : 91815541 ...

  7. ACM职业生涯回忆录学习方法感悟

    2018年的5月,我在西安邀请赛打铁,陕西省赛三等奖.2019年的5月,还是在西工大,邀请赛拿金,圆满退役.(不过省赛才第十不是很满意呜呜呜) 2018年年底区域赛赛季结束的时候,我被问到明年区域赛是 ...

  8. 【菜鸟源码模板】最新素材下载类网站 带会员充值系统 HTML5自适应手机版

    介绍: 一款非常大气的站长素材下载类网站源码,带会员系统,带充值系统. 1.该模板由站长亲自制作,代码干净整洁; 2.效果相当的炫酷,相当简洁大气高端,模板简单,全部已数据调用,只需后台修改栏目名称即 ...

  9. acm - 动态规划模板

    动态规划 思维导图: 数字三角形模型 每次只能向下走或者向右走.从起点走到终点. 题目给定一个 n × n n \times n n×n 的矩阵,矩阵中的每个格子上有一个价值为 w w w 的物品.给 ...

最新文章

  1. eclipse中中文字体过小
  2. 百雀羚、林清轩、逐本走红背后,植物基护肤品的春天来了?
  3. git放弃本地修改,强制覆盖本地文件
  4. 面试时被问到「有没有职业规划时」,要怎么回答?
  5. 一个USB HUB电路分享
  6. cbrt c语音_C语言有哪些鲜为人知的特性?
  7. List<?> list= new ArrayList<?>接口引用指向实现类的对象.
  8. Oracle 12.2 新特性 | PDB不同字符集变更深入解析
  9. 快递实名制正式实施 市民最担心个人信息泄露
  10. 使用SoapUI测试Web Service
  11. Redis 经典 必问21问,BAT面试都会问,你会回答吗?
  12. 解决Mac安装Adobe软件错误代码501问题(PS AI AE PR)mac安装Adobe软件报错501解决方案
  13. 依行科技日常实习面经
  14. zMUD里的颜色触发
  15. 使用torchvision.models
  16. TinyG 入门06
  17. 8句极易踩中买家雷点的口头禅,你中了哪几条?
  18. xheditor使用
  19. 啃光学论文的笔记(1)
  20. 和Leo一起做爱线段树的好孩子HDU5238 Calculator

热门文章

  1. 【孙伟】基础实用Photoshop设计软件标准视频教程-孙伟-专题视频课程
  2. HADOOP实战——蔬菜价格统计(win10伪分布式环境)
  3. 杭州电子科技大学信息工程学院,计算机本科生考研情况很弱?
  4. 使用SSD训练自己的模型(从图片标注开始)
  5. 超级Windows快捷键大全
  6. 教你选择巫师之怒里最适合自己的职业
  7. linux写入二进制文件内容,fopen , fread fwrite 函数读写二进制文件 问题总结
  8. python脚本如何自动升级?
  9. 开源大师章文嵩打造低碳淘宝 称技术人才创新很重要
  10. apex英雄机器人探路者怎么玩_Apex英雄探路者怎么玩 探路者人物操作技巧分享