• 模板


    不时更新常用的模板,模板可能写的有些早,不像现在写的一样

    数论

    组合数递推公式

    1 C[1][0] = C[1][1] = 1;
    2 for (int i=2; i<=N; i++)
    3 {
    4     C[i][0] = 1;
    5     for (int j=1; j<=N; j++)
    6         C[i][j] = C[i-1][j]+C[i-1][j-1];
    7 }
    View Code

    求逆元

    a扩展欧几里得求逆元

     1 #include<cstdio>
     2 
     3 int exgcd(int a,int b,int &x,int &y)
     4 {
     5     if (b==0)
     6     {
     7         x = 1;
     8         y = 0;
     9         return a;
    10     }
    11     int r = exgcd(b,a%b,x,y);
    12     int tmp = x;
    13     x = y;
    14     y = tmp-a/b*y;
    15     return r;
    16 }
    17 
    18 int main()
    19 {
    20     //gcd(a,p)==1
    21     int a,p,r,x,y;
    22     while (scanf("%d%d",&a,&p)!=EOF)
    23     {
    24         r = exgcd(a,p,x,y);
    25         printf("%d",(x%p+p)%p);
    26     }
    27     return 0;
    28 }
    View Code

    b线性求逆元

     1 int inv[MAXN]; 
     2 void INV() //线性求到a的逆元 
     3 {
     4     inv[1] = 1;
     5     for (int i=2; i<=n; ++i) {
     6         inv[i] = (1ll*(-(p/i))*inv[p%i])%p;
     7         inv[i] = (inv[i]+p)%p;
     8     }
     9 }
    10 
    11 /*-----------------------------------------------*/
    12 
    13 int INV(int a)//线性求a的逆元,可以记忆化 
    14 {
    15     if (a==1) return 1;
    16     return ((-(p/a)*INV(p%a))%p);
    17 }
    View Code

    c线性求阶乘的逆元 

    /*
    假设知道了模p下a阶乘的逆元b,fac[a] * b ≡ 1 (mod p)
    那么a-1的阶乘的逆元就是,fac[a-1] * a * b ≡ 1 (mod p)
    所以 b * a 就是a-1的阶乘的逆元。
    */
    ifac[1000000] = ksm(1000000, mod - 2);
    for (int i=1000000; i>=1; --i) ifac[i - 1] = ifac[i] * i % mod;
    View Code 

    中国剩余定理51nod1079

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline LL read() {
     6     LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 
    11 LL a[100], m[100];
    12 
    13 LL inv(LL a,LL b,LL p) {
    14     LL res = 1;
    15     while (b) {
    16         if (b & 1) res = res * a % p;
    17         a = a * a % p;
    18         b >>= 1;
    19     }
    20     return res;
    21 }
    22 
    23 int main() {
    24     
    25     int n;scanf("%d",&n);
    26     LL M = 1;
    27     
    28     for (int i=1; i<=n; ++i) {
    29         m[i] = read();
    30         a[i] = read();
    31         M = M * m[i];
    32     }
    33 
    34         
    35     LL Ans = 0;
    36     for (int i=1; i<=n; ++i) {
    37         LL Mi = M / m[i];
    38         LL T = inv(Mi,m[i]-2,m[i]);
    39         Ans = (Ans + a[i] * T * Mi) % M;
    40     }
    41     cout << (Ans % M + M) % M;
    42     return 0;
    43 }
    View Code

    扩展中国剩余定理POJ2891

     1 #include<cstdio>
     2 #include<cctype>
     3 using namespace std;
     4 typedef long long LL;
     5 
     6 inline int read() {
     7     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     8     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     9 }
    10 
    11 LL gcd(LL a, LL b) {
    12     return b == 0 ? a : gcd(b, a%b);
    13 }
    14 
    15 void exgcd(LL a,LL b,LL &x,LL &y) {
    16     if (b == 0) {
    17         x = 1,b = 0;
    18         return ;
    19     }
    20     exgcd(b,a%b,x,y);
    21     LL t = x;
    22     x = y;
    23     y = t - a / b * y;
    24 }
    25 
    26 LL inv(LL a,LL b) {
    27     LL x = 0,y = 0;
    28     exgcd(a,b,x,y);
    29     x = (x % b + b) % b;
    30     while (x <= 0) x += b;
    31     return x;
    32 }
    33 
    34 LL m[1010],a[1010];
    35 
    36 int main() {
    37     int n;
    38     while (scanf("%d",&n) != EOF) {
    39         bool flag = true;
    40         for (int i=1; i<=n; ++i) {
    41             scanf("%lld%lld",&m[i],&a[i]);
    42         }
    43         LL m1,m2,a1,a2,c,d;
    44         for (int i=2; i<=n; ++i) {
    45             m1 = m[i-1], m2 = m[i], a1 = a[i-1], a2 = a[i], c = a2 - a1;
    46             d = gcd(m1, m2);
    47             if (c % d) {flag = false;break;}
    48             m[i] = m1 * m2 / d;
    49             a[i] = inv(m1/d, m2/d) * (c / d) % (m2 / d) * m1 + a1;
    50             a[i] = (a[i] % m[i] + m[i]) % m[i];
    51         }
    52         if (!flag) puts("-1");
    53         else printf("%lld
    ",a[n]);
    54     }
    55     return 0;
    56 }
    View Code

    矩阵乘法求斐波那契,矩阵快速幂(第一项是1,第二项是1)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 const int mod = 1e9+7;
     8 const int N = 2;
     9 
    10 struct Matrix{
    11     int a[N][N];
    12     Matrix(){
    13         this->clear();
    14     }
    15     void clear(){
    16         memset(a,0,sizeof(a));
    17     }
    18     void setone(){
    19         this->clear();
    20         for (int i=0; i<N; ++i)
    21             a[i][i] = 1;
    22     }
    23     Matrix operator * (const Matrix &x) const 
    24     {
    25         Matrix c;
    26         for (int k=0; k<N; k++)
    27             for (int i=0; i<N; ++i)
    28                 for (int j=0; j<N; ++j)
    29                     c.a[i][j] = (c.a[i][j]+1ll*a[i][k]*x.a[k][j])%mod;
    30         return c;
    31     }
    32 };
    33 
    34 int fibn(int n)
    35 {
    36     Matrix x,s;
    37     x.a[0][0] = x.a[0][1] = x.a[1][0] = 1;
    38     s.setone();
    39     for (; n; n>>=1)
    40     {
    41         if (n&1) s = s*x;
    42         x = x*x; 
    43     }
    44     return (s.a[0][0]+s.a[0][1])%mod;
    45 }
    46 int main()
    47 {
    48     int n;
    49     while (~scanf("%d",&n))
    50     {
    51         if (n==1||n==2) puts("1");
    52         else printf("%d
    ",fibn(n-2));
    53     }
    54     return 0;
    55 }
    重载运算符
     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 const int mod = 1e9+7;
     7 const int N = 2;
     8 
     9 struct Matrix{
    10     int a[N][N];
    11     Matrix () {memset(a,0,sizeof(a));}
    12 }t;
    13 Matrix mul(Matrix a,Matrix b) {
    14     Matrix c;
    15     for (int k=0; k<N; k++)
    16         for (int i=0; i<N; ++i)
    17             for (int j=0; j<N; ++j)
    18                 c.a[i][j] = (c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%mod;
    19     return c;
    20 }
    21 int fibn(int n) {
    22     Matrix x,s;
    23     x.a[0][0] = x.a[0][1] = x.a[1][0] = 1;
    24     s.a[0][0] = s.a[1][1] = 1;
    25     while (n) {
    26         if (n&1) s = mul(s,x);
    27         x = mul(x,x); 
    28         n >>= 1;
    29     }
    30     return (s.a[0][0]+s.a[0][1])%mod;
    31 }
    32 int main() {
    33     int n;
    34     while (~scanf("%d",&n)) {
    35         if (n==1||n==2) puts("1");
    36         else printf("%d
    ",fibn(n-2));
    37     }
    38     return 0;
    39 }
    函数版

    线性筛素数O(n)

    1 for (int i=2; i<=N; i++) {
    2     if (!noprime[i]) {
    3         prime[++tot]=i;
    4     }
    5     for (int j=1; j<=tot&&i*prime[j]<=N; j++) {
    6         noprime[i*prime[j]] = true;
    7         if(i % prime[j] == 0) break ;  
    8     }
    9 }
    View Code

    线性筛欧拉函数

     1 for (int i=2; i<=N; i++) {
     2     if (!noprime[i]) {
     3         prime[++tot]=i;
     4         phi[i] = i-1; 
     5     }
     6     for (int j=1; j<=tot&&i*prime[j]<=N; j++) {
     7         noprime[i*prime[j]] = true;
     8         if(i % prime[j] == 0) {
     9             phi[i * prime[j]] = phi[i] * prime[j];
    10             break ; //重要 
    11         }
    12         else phi[i * prime[j]] = phi[i]*(prime[j]-1);
    13     }
    14 }
    View Code

    线性筛莫比乌斯函数

     1 void getmu() {
     2     mu[1] = 1;
     3     for (int i=2; i<=N; ++i) {
     4         if (!noprime[i]) prime[++tot] = i,mu[i] = -1;
     5         for (int j=1; j<=tot&&i*prime[j]<=N; ++j) {
     6             noprime[i * prime[j]] = true;
     7             if (i % prime[j] == 0) {mu[i * prime[j]] = 0; break;}
     8             mu[i * prime[j]] = - mu[i];
     9         }
    10     }
    11 }
    View Code

    求组合数(很大!)

    一般的逆元求解

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1000000;
     4 const int mod=1000000007;
     5 
     6 int f[maxn+10];
     7 void init(){//阶乘
     8     f[0]=1;
     9     for(int i=1;i<=maxn;i++){
    10         f[i]=1ll*f[i-1]*i%mod;
    11     }
    12 }
    13 
    14 int fast(int a,int n){
    15     if (n==0) return 1;
    16     if (n%2) return 1ll*a*fast(a,n-1)%mod;
    17     int tmp=fast(a,n/2);
    18     return 1ll*tmp*tmp%mod;
    19 }
    20 
    21 int C(int n,int m){
    22     if(n==m||m==0)return 1;
    23     return (1ll*f[n]*fast(f[m],mod-2)%mod)*fast(f[n-m],mod-2)%mod;
    24 }
    25 
    26 int main(){
    27     init();
    28     int n,m,k;
    29     scanf("%d%d%d",&n,&m,&k);
    30     int x = n-k,y = m-1;
    31         printf("%d
    ",C(x,y));
    32     return 0;
    33 }
    View Code

    Lucas定理

     1 //适用于p很小,n,m很大 或者 n,m不大但大于p
     2 #include<cstdio>
     3 
     4 typedef long long LL;
     5 const int N = 1000010;
     6 
     7 LL n,m,p,f[N];
     8 
     9 void init(int x) {
    10     f[0] = 1;
    11     for (int i=1; i<=x; ++i) f[i] = (i * f[i-1]) % x;
    12 }
    13 LL ksm(LL a,LL b) {
    14     LL ans = 1;
    15     while (b) {
    16         if (b & 1) ans = (ans * a) % p;
    17         b >>= 1;
    18         a = (a * a) % p;
    19     }
    20     return ans;
    21 }
    22 LL C(LL n,LL m) {
    23     if (m > n) return 0;
    24     return (f[n] * ksm(f[m],p-2)) % p * ksm(f[n-m],p-2) % p;
    25 }
    26 LL Lucas(LL n,LL m) {
    27     if (m == 0) return 1;
    28     else return (C(n%p,m%p) * Lucas(n/p,m/p)) % p;
    29 }
    30 int main() {
    31     int T;
    32     scanf("%d",&T);
    33     while (T--) {
    34         scanf("%lld%lld%lld",&n,&m,&p);
    35         init(p);
    36         printf("%lld
    ",Lucas(n,m));
    37     }
    38     return 0;
    39 }
    View Code

    快速幂

    1 int ksm(int a,int b,int p) {
    2     int ret = 1;
    3     while (b) {
    4         if (b & 1) ret = (1ll*ret*a) % p;
    5         a = (1ll*a*a)%p;
    6         b >>= 1;
    7     }
    8     return ret%p;
    9 }
    View Code

    快速乘

    1 int ksc(int a,int b,int p) {
    2     int ret = 0;
    3     while (b) {
    4         if (b & 1) ret = (ret+a)%p;
    5         a = (a+a)%p;
    6         b >>= 1;
    7     }
    8     return ret;
    9 }
    View Code

    素数判定Miller_Rabin

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<ctime>
     5 
     6 using namespace std;
     7 
     8 typedef long long LL;
     9 
    10 LL ksm(LL a,LL b,LL p) {
    11     LL ans = 1;
    12     a = a % p;
    13     while (b) {
    14         if (b & 1) ans = (ans * a) % p;
    15         a = (a * a) % p;
    16         b >>= 1;
    17     }
    18     return ans;
    19 }
    20 bool witness(LL a,LL n,LL d,LL r) {
    21     LL ret = ksm(a,d,n);
    22     LL last = ret;
    23     while (r--) {
    24         ret = ret * ret % n;
    25         if (ret==1 && last!=1 && last!=n-1) return false;
    26         last = ret;
    27     }
    28     if (ret != 1) return false;
    29     return true;
    30 }
    31 bool miller_rabin(LL n) {
    32     if (n==2) return true;
    33     if (n==1 || (n&1)==0) return false;
    34     LL d = n - 1,r = 0;
    35     while ((d&1)==0) r++,d>>=1;
    36     for (LL i=1; i<=20; ++i) {
    37         LL a = rand()%(n-1)+1;
    38         if (!witness(a,n,d,r)) return false;
    39     }
    40     return true;
    41 }
    42 int main () {
    43     srand((unsigned)time(NULL));
    44     LL a,b;
    45     while (cin >> a) {
    46         if (miller_rabin(a)) cout << "yes
    ";
    47         else cout << "no
    ";    
    48     }
    49     return 0;
    50 }
    View Code

    FFT

    递归

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 
     7 using namespace std;
     8 const int N = 300100;
     9 const double eps = 1e-8;
    10 const double pi = acos(-1.0);
    11 typedef long long LL;
    12 
    13 struct Complex {
    14     double x,y;
    15     Complex() {x=0,y=0;}
    16     Complex(double xx,double yy) {x=xx,y=yy;}
    17 
    18 }A[N],B[N];
    19 
    20 Complex operator + (Complex a,Complex b) {
    21     return Complex(a.x+b.x,a.y+b.y);
    22 }
    23 Complex operator - (Complex a,Complex b) { 
    24     return Complex(a.x-b.x,a.y-b.y);
    25 }
    26 Complex operator * (Complex a,Complex b) {
    27     return Complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);
    28 }
    29 
    30 void FFT(Complex *a,int n,int ty) {
    31     if (n==1) return ;
    32     Complex a1[n>>1],a2[n>>1];
    33     for (int i=0; i<=n; i+=2) {
    34         a1[i>>1] = a[i],a2[i>>1] = a[i+1];
    35     }
    36     FFT(a1,n>>1,ty);
    37     FFT(a2,n>>1,ty);
    38     Complex w1 = Complex(cos(2.0*pi/n),ty*sin(2.0*pi/n));
    39     Complex w = Complex(1.0,0.0);
    40     for (int i=0; i<(n>>1); i++) {
    41         Complex t = w * a2[i];
    42         a[i+(n>>1)] = a1[i] - t;
    43         a[i] = a1[i] + t;
    44         w = w * w1;
    45     }
    46 }
    47 int main() {
    48     int n,m;
    49     scanf("%d%d",&n,&m);
    50     for (int i=0; i<=n; ++i) scanf("%lf",&A[i].x);
    51     for (int i=0; i<=m; ++i) scanf("%lf",&B[i].x);
    52     int fn = 1;
    53     while (fn <= n+m) fn <<= 1;
    54     FFT(A,fn,1);
    55     FFT(B,fn,1);
    56     for (int i=0; i<=fn; ++i) 
    57         A[i] = A[i] * B[i];
    58     FFT(A,fn,-1);
    59     for (int i=0; i<=n+m; ++i) 
    60         printf("%d ",(int)(A[i].x/fn+0.5));
    61     return 0;
    62 }
    View Code

    非递归

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 
     7 using namespace std;
     8 const int N = 300100;
     9 const double eps = 1e-8;
    10 const double pi = acos(-1.0);
    11 typedef long long LL;
    12 
    13 struct Complex {
    14     double x,y;
    15     Complex() {x=0,y=0;}
    16     Complex(double xx,double yy) {x=xx,y=yy;}
    17 
    18 }A[N],B[N];
    19 
    20 Complex operator + (Complex a,Complex b) {
    21     return Complex(a.x+b.x,a.y+b.y);
    22 }
    23 Complex operator - (Complex a,Complex b) { 
    24     return Complex(a.x-b.x,a.y-b.y);
    25 }
    26 Complex operator * (Complex a,Complex b) {
    27     return Complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);
    28 }
    29 void FFT(Complex a[],int n,int ty) {
    30     for (int i=0,j=0; i<n; ++i) {
    31         if (i < j) swap(a[i],a[j]);
    32         for (int k=n>>1; (j^=k)<k; k>>=1);//-----
    33     }
    34     for (int s=1; (1<<s)<=n; ++s) {
    35         int m = (1 << s);
    36         Complex w1 = Complex(cos(2*pi/m),ty*sin(2*pi/m));
    37         for (int i=0; i<n; i+=m) {
    38             Complex w = Complex(1,0);
    39             for (int k=0; k<(m>>1); ++k) {
    40                 Complex t = w*a[i+k+(m>>1)];
    41                 a[i+k+(m>>1)] = a[i+k] - t;//-----
    42                 a[i+k] = a[i+k] + t; //-----
    43                 w = w*w1;
    44             }
    45         }
    46     }
    47 }
    48 int main() {
    49     int n,m;
    50     scanf("%d%d",&n,&m);
    51     for (int i=0; i<=n; ++i) scanf("%lf",&A[i].x);
    52     for (int i=0; i<=m; ++i) scanf("%lf",&B[i].x);
    53     int fn = 1;
    54     while (fn <= n+m) fn <<= 1;
    55     FFT(A,fn,1);
    56     FFT(B,fn,1);
    57     for (int i=0; i<=fn; ++i) 
    58         A[i] = A[i] * B[i];
    59     FFT(A,fn,-1);
    60     for (int i=0; i<=n+m; ++i) 
    61         printf("%d ",(int)(A[i].x/fn+0.5));
    62     return 0;
    63 }
    View Code

    图论

    树上倍增lca模板(例题https://www.luogu.org/problem/show?pid=3379

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 const int N = 1000100;
     7 
     8 struct Edge{
     9     int v,nxt;
    10 }e[N];
    11 int fa[N][25];    //开25,一开始开的20,找了好长时间的错误 
    12 int deth[N];    
    13 int head[N];
    14 int n,m,s,cnt,a,b,d;
    15 
    16 void add(int u,int v)
    17 {
    18     cnt++;
    19     e[cnt].v = v;
    20     e[cnt].nxt = head[u];
    21 //    e[cnt]=(Edge) {v,head[u]};    
    22     head[u] = cnt;
    23 }
    24 
    25 void dfs(int x)
    26 {
    27     for (int i=head[x]; i; i=e[i].nxt)
    28     {
    29         int v = e[i].v;
    30         if(!deth[v])//判重,因为扫过的点都有了深度,也可以另设一个v数组 
    31         {
    32             deth[v] = deth[x]+1;
    33             fa[v][0] = x;
    34             dfs(v);
    35         }
    36     }
    37 }
    38 
    39 void init()
    40 {
    41     for (int j=1; j<=20; ++j)
    42         for (int i=1; i<=n; ++i)
    43             fa[i][j] = fa[fa[i][j-1]][j-1];
    44 }
    45 
    46 int lca(int u,int v)
    47 {
    48     if (deth[u] < deth[v]) swap(u,v);
    49     /*for (int i=20; i>=0; --i)    
    50     {
    51         if (deth[fa[u][i]] >= deth[v])
    52             u = fa[u][i];
    53     }*/
    54     d = deth[u]-deth[v];    //位运算 
    55     for (int i=0; i<=20; ++i)
    56     {
    57         if ((1<<i) & d)
    58             u = fa[u][i];
    59     }
    60     if (u==v) return u;
    61     for (int i=20; i>=0; --i)
    62     {
    63         if(fa[u][i] != fa[v][i])
    64         {
    65             u = fa[u][i];
    66             v = fa[v][i];
    67         }
    68     }
    69     return fa[u][0];
    70 }
    71 
    72 int main()
    73 {
    74     scanf("%d%d%d",&n,&m,&s);
    75     for (int i=1; i<n; ++i)
    76     {
    77         scanf("%d%d",&a,&b);
    78         add(a,b);
    79         add(b,a);
    80     }
    81     deth[s] = 1;
    82     fa[s][0] = 0;
    83     dfs(s);
    84     init();
    85     for (int i=1; i<=m; ++i)
    86     {
    87         scanf("%d%d",&a,&b);
    88         printf("%d
    ",lca(a,b));
    89     }
    90     return 0;
    91 }
    View Code

    求树的直径

     1 /*
     2 我们在树上任选一个节点u,以这个点为根进行一遍dfs,可以求出距离点u最远的点s,
     3 再由s为根进行一遍dfs,找到距离s最远的点t,点s与点t之间的路径即为树的直径。
     4 */
     5 
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<vector>
     9 #include<algorithm>
    10 using namespace std;
    11 const int MAXN = 100010;
    12 int dis[MAXN];
    13 vector<int>tree[MAXN];
    14 
    15 void dfs(int now)
    16 {
    17     for (int i=0; i<tree[now].size(); ++i)
    18     {
    19         if (!dis[tree[now][i]])
    20         {
    21             dis[tree[now][i]] = dis[now]+1;
    22             dfs(tree[now][i]);
    23         }
    24     }
    25 }
    26 
    27 int main()
    28 {
    29     int n,t,ans;
    30     scanf("%d",&n);
    31     for (int u,v,i=1; i<n; ++i)
    32     {
    33         scanf("%d%d",&u,&v);
    34         tree[u].push_back(v);
    35         tree[v].push_back(u);
    36     }
    37     t = 1;
    38     dis[t] = 0;
    39     dfs(t);
    40     for (int i=1; i<=n; ++i)
    41         if (dis[i]>dis[t]) t = i;
    42     memset(dis,0,sizeof(dis));
    43     dis[t] = 0;
    44     dfs(t);
    45     ans = 1;
    46     for (int i=1; i<n; ++i)
    47         if (dis[i]>dis[ans]) ans = i;
    48     printf("%d",dis[ans]);
    49     return 0;
    50 }
    View Code

    最小生成树 kruskal 算法(例题https://www.luogu.org/problem/show?pid=3366

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 struct edge{
     8     int a,b,c;
     9 }e[200100];
    10 int n,m;
    11 int far[5100];
    12 int ans,cnt;
    13 
    14 int find(int a)
    15 {
    16     return far[a]==a?a:far[a]=find(far[a]);
    17 }
    18 bool cmp(edge a,edge b)
    19 {
    20     return a.c<b.c;
    21 }
    22 
    23 int main()
    24 {
    25     scanf("%d%d",&n,&m);
    26     for(int i=1;i<=n;++i) far[i] = i;
    27     for(int i=1;i<=m;++i)
    28     {
    29         int a,b,c;
    30         scanf("%d%d%d",&a,&b,&c);
    31         e[i].a=a;
    32         e[i].b=b;
    33         e[i].c=c;
    34     }
    35     sort(e+1,e+m+1,cmp);
    36     for(int i=1;i<=m;++i)
    37     {
    38         int aa = find(e[i].a);
    39         int bb = find(e[i].b);
    40         if(aa!=bb)
    41         {
    42             cnt++;
    43             far[aa] = bb;
    44             ans += e[i].c;
    45             if(cnt==(n-1))break;
    46         }
    47     }
    48     if(cnt==(n-1)) cout<<ans;
    49     else cout<<"orz";
    50     return 0;
    51 }
    View Code

    最短路 spfa 算法 (例题https://www.luogu.org/problem/show?pid=3371

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 const int MAXN = 10100;
     7 
     8 struct Edge{
     9     int to,w,nxt;
    10 }e[500100];
    11 
    12 int dis[MAXN];
    13 int head[MAXN];
    14 bool vis[MAXN];
    15 queue<int>q;
    16 int n,m,s,cnt;
    17 
    18 void add(int u,int v,int w)    //从u到v有一条长度是w的边 
    19 {
    20     ++cnt;
    21     e[cnt].to = v;
    22     e[cnt].w = w;
    23     e[cnt].nxt = head[u];
    24     head[u] = cnt;
    25 }
    26 
    27 void spfa()
    28 {
    29     for (int i=1; i<=n; ++i)
    30         dis[i] = 2147483647;
    31     dis[s] = 0;
    32     q.push(s);
    33     vis[s] = true;
    34     while (!q.empty())
    35     {
    36         int u = q.front();
    37         q.pop();
    38         for (int i=head[u]; i; i=e[i].nxt)
    39         {
    40             int v = e[i].to;
    41             int w = e[i].w;
    42             if (dis[v]>dis[u]+w)
    43             {
    44                 dis[v] = dis[u]+w;
    45                 if (!vis[v])
    46                 {
    47                     q.push(v);
    48                     vis[v] = true;
    49                 }
    50             }
    51         }
    52         vis[u] = false;
    53     }
    54 }
    55 
    56 int main()
    57 {
    58     scanf("%d%d%d",&n,&m,&s);
    59     for (int u,v,w,i=1; i<=m; ++i)
    60     {
    61         scanf("%d%d%d",&u,&v,&w);
    62         add(u,v,w);    //有向图,如果是无向图加一行add(v,u,w); 
    63     }
    64     spfa();
    65     for (int i=1; i<=n; ++i)
    66         printf("%d ",dis[i]);
    67     return 0;
    68 }
    View Code

    最短路 dijkstra 算法

     1 const int  MAXN = 1010;
     2 int dis[MAXN];
     3 int pre[MAXN];
     4 int w[MAXN][MAXN];
     5 bool vis[MAXN];    // 判断是否已存入该点松弛过 
     6 int n; //
     7 
     8 void Dijkstra(int st)
     9 {
    10     for (int i=1; i<=n; ++i) dis[i] = w[st][i];
    11     dis[st] = 0;
    12     vis[st] = true;
    13     pre[st] = 0;
    14     for (int i=1; i<=n-1; i++)
    15     {
    16         int minn = 1e8;
    17         int u = 0;                    // 找出当前未使用的点j的dist[j]最小值
    18         for (int j=1; j<=n; ++j)
    19             if (!vis[j] && dis[j]<minn)
    20             {
    21                 u = j;                // u保存当前邻接点中距离最小的点的号码 
    22                 minn = dis[j];
    23             }
    24         if (u==0) break;
    25         vis[u] = true; 
    26         for(int v=1; v<=n; v++)
    27             if(dis[u] + w[u][v] < dis[v])    //在通过新加入的u点路径找到离v0点更短的路径  
    28             {
    29                 dis[v] = dis[u]+w[u][v];    //更新dist 
    30                 pre[v] = u;                    //记录前驱顶点 
    31             }
    32     }
    33 }
    View Code

    堆优化的dijkstra

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 
     5 using namespace std;
     6 
     7 const int N = 10100;
     8 const int M = 500100;
     9 
    10 struct Edge{
    11     int to,nxt,w;
    12 }e[M]; 
    13 struct Node{
    14     int x,dis;
    15     bool operator < (const Node &a) const {
    16         return dis > a.dis;
    17     }
    18     Node() {}
    19     Node(int a,int b) {x = a,dis = b;}
    20 }now;
    21 int head[N],tot,dis[N];
    22 bool vis[N];
    23 priority_queue<Node>q;
    24 int n,m,s;
    25 
    26 inline int read() {
    27     int x = 0,f = 1;char ch = getchar();
    28     for (; ch<'0'||ch>'9'; ch = getchar())
    29         if (ch=='-') f = -1;
    30     for (; ch>='0'&&ch<='9'; ch = getchar())
    31         x = x*10+ch-'0';
    32     return x*f;
    33 }
    34 inline void add_edge(int u,int v,int w) {
    35     e[++tot].to = v,e[tot].w = w,e[tot].nxt = head[u],head[u] = tot;
    36 //    e[++tot].to = u,e[tot].w = w,e[tot].nxt = head[v],head[v] = tot;
    37 }
    38 void Dijkstra() {
    39     for (int i=1; i<=n; ++i) dis[i] = 2147483647;
    40     memset(vis,false,sizeof(vis));
    41     dis[s] = 0;
    42     q.push(Node(s,0));
    43     while (!q.empty()) {
    44         now = q.top();
    45         q.pop();
    46         int u = now.x;
    47         if (vis[u]) continue;
    48         vis[u] = true;
    49         for (int i=head[u]; i; i=e[i].nxt) {
    50             int v = e[i].to,w = e[i].w;
    51             if (dis[v] > dis[u]+w) {
    52                 dis[v] = dis[u]+w;
    53                 q.push(Node(v,dis[v]));
    54             }
    55         }
    56         
    57     }
    58 }
    59 int main() {
    60     n = read(),m = read(),s = read();
    61     for (int i=1; i<=m; ++i) {
    62         int u = read(),v = read(),w = read();
    63         add_edge(u,v,w);
    64     }
    65     Dijkstra();
    66     for (int i=1; i<=n; ++i) printf("%d ",dis[i]);
    67     return 0;    
    68 }
    View Code

    网络流dinic算法

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int MAXN = 100100;
     8 const int INF = 1e9;
     9 
    10 struct Edge{
    11     int to,c,nxt;
    12     Edge(){}
    13     Edge(int tt,int cc,int nn) {to = tt,c = cc,nxt = nn;}
    14 }e[1000100];
    15 queue<int>q;
    16 
    17 int head[MAXN],dis[MAXN];
    18 int s,t,n,m,tot = 1;
    19 
    20 int read()
    21 {
    22     int x = 0, f = 1;char ch = getchar();
    23     while (ch<'0'||ch>'9') {if (ch=='-') f = -1; ch = getchar();}
    24     while (ch>='0'&&ch<='9') {x = x*10+ch-'0'; ch = getchar();}
    25     return x*f;
    26 }
    27 bool bfs()
    28 {
    29     q.push(s);
    30     memset(dis,-1,sizeof(dis));
    31     dis[s] = 0;
    32     while (!q.empty())
    33     {
    34         int u = q.front();
    35         q.pop();
    36         for (int i=head[u]; i; i=e[i].nxt)
    37         {
    38             int v = e[i].to;
    39             if (dis[v]==-1&&e[i].c>0)
    40             {
    41                 dis[v] = dis[u]+1;
    42                 q.push(v);
    43             }
    44         }
    45     }
    46     if (dis[t]!=-1) return true;
    47     return false;
    48 }
    49 int dfs(int u,int low)
    50 {
    51     if (u==t) return low;
    52     int w,used = 0;
    53     for (int i=head[u]; i; i=e[i].nxt)
    54     {
    55         int v = e[i].to;
    56         if (dis[v]==dis[u]+1&&e[i].c>0)
    57         {
    58             w = dfs(v,min(low-used,e[i].c));
    59             e[i].c -= w;
    60             e[i^1].c += w;
    61             used += w;
    62             if (used==low) return low;
    63         }
    64     }
    65     if (!used) dis[u] = -1;
    66     return used;
    67 }
    68 int dinic()
    69 {
    70     int ans = 0,t;
    71     while (bfs())
    72         ans += dfs(s,INF);
    73     return ans;
    74 }
    75 int main()
    76 {
    77     n = read();m = read();s = read();t = read();
    78     for (int u,v,w,i=1; i<=m; ++i)
    79     {
    80         u = read();v = read();w = read();
    81         e[++tot] = Edge(v,w,head[u]);
    82         head[u] = tot;
    83         e[++tot] = Edge(u,0,head[v]);
    84         head[v] = tot;    
    85     }
    86     printf("%d",dinic());
    87     return 0;
    88 }
    View Code

    KM算法 HDU2255

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long LL;
     7 
     8 inline int read() {
     9     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    10     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    11 }
    12 
    13 const int INF = 1e9;
    14 const int N = 305; //--
    15 int match[N], mp[N][N], lx[N], ly[N], slack[N];
    16 bool visx[N], visy[N];
    17 int n;
    18 
    19 bool dfs(int u) {
    20     visx[u] = true;
    21     for (int v=1; v<=n; ++v) {
    22         if (visy[v]) continue;
    23         int t = lx[u] + ly[v] - mp[u][v];
    24         if (!t) {
    25             visy[v] = true;
    26             if (!match[v] || dfs(match[v])) {
    27                 match[v] = u;
    28                 return true;
    29             }
    30         }
    31         else slack[v] = min(slack[v], t);
    32     }
    33     return false;
    34 }
    35 void KM() {
    36     memset(match, 0, sizeof(match));
    37     memset(ly, 0, sizeof(ly));
    38     for (int i=1; i<=n; ++i) 
    39         for (int j=1; j<=n; ++j) 
    40             lx[i] = max(lx[i], mp[i][j]);
    41             
    42     for (int x=1; x<=n; ++x) {
    43         for (int i=1; i<=n; ++i) slack[i] = INF;
    44         while (true) {
    45             memset(visx, false, sizeof(visx));
    46             memset(visy, false, sizeof(visy));
    47             if (dfs(x)) break;
    48             int d = INF;
    49             for (int i=1; i<=n; ++i) 
    50                 if (!visy[i]) d = min(d, slack[i]);
    51             for (int i=1; i<=n; ++i) {
    52                 if (visx[i]) lx[i] -= d;
    53                 if (visy[i]) ly[i] += d;
    54                 else slack[i] -= d;
    55             }
    56         }
    57     }
    58 }
    59 int main() {
    60     while (~scanf("%d",&n)) {
    61         for (int i=1; i<=n; ++i) 
    62             for (int j=1; j<=n; ++j) mp[i][j] = read();    
    63         KM();
    64         int ans = 0;
    65         for (int i=1; i<=n; ++i) 
    66             if (match[i]) ans += mp[match[i]][i];
    67         printf("%d
    ",ans);
    68     }
    69     return 0;
    70 }
    View Code

    数据结构

    树状数组,单点查询,区间修改(例题https://www.luogu.org/problem/show?pid=3368)需要用到差分的思想,即数列前后两个数的差。数组不需要开四倍

     1 //树状数组:区间修改,单点查询,差分 
     2 #include<cstdio>
     3 int sum[500100];
     4 int n,m,last = 0;
     5 int lowbit(int x)
     6 {
     7     return x&(-x);
     8 }
     9 void update(int x,int v)
    10 {
    11     while (x<=n)
    12     {
    13         sum[x] += v;
    14         x += lowbit(x);
    15     }
    16 }
    17 int query(int x)
    18 {
    19     int ans = 0;
    20     while (x)
    21     {
    22         ans += sum[x];
    23         x -= lowbit(x);
    24     }
    25     return ans;
    26 }
    27 int main()
    28 {
    29     scanf("%d%d",&n,&m);
    30     for (int a,i=1; i<=n; ++i)
    31     {
    32         scanf("%d",&a);
    33         update(i,a-last);
    34         last = a;
    35     }
    36     for (int x,y,z,a,i=1; i<=m; ++i)
    37     {
    38         scanf("%d",&a);
    39         if (a==1)    //区间修改
    40         {
    41             scanf("%d%d%d",&x,&y,&z);
    42             update(x,z);
    43             update(y+1,-z); 
    44         } 
    45         else        //单点查询 
    46         {
    47             scanf("%d",&x);
    48             printf("%d
    ",query(x));
    49         }
    50     }
    51     return 0;
    52 }
    View Code

    树状数组,单点修改,区间查询(例题https://www.luogu.org/problem/show?pid=3374)这个不需要用差分

     1 //树状数组:区间查询,单点修改 
     2 #include<cstdio>
     3 int sum[500100];
     4 int n,m;
     5 int lowbit(int x)
     6 {
     7     return x&(-x);
     8 }
     9 void update(int x,int v)
    10 {
    11     while (x<=n)
    12     {
    13         sum[x] += v;
    14         x += lowbit(x);
    15     }
    16 }
    17 int query(int x)
    18 {
    19     int ans = 0;
    20     while (x)
    21     {
    22         ans += sum[x];
    23         x -= lowbit(x);
    24     }
    25     return ans;
    26 }
    27 int main()
    28 {
    29     scanf("%d%d",&n,&m);
    30     for (int a,i=1; i<=n; ++i)
    31     {
    32         scanf("%d",&a);
    33         update(i,a);
    34     }
    35     for (int i=1; i<=m; ++i)
    36     {
    37         int x,y,z;
    38         scanf("%d%d%d",&z,&x,&y);
    39         if (z==1) update(x,y);    //单点修改 
    40         else printf("%d
    ",query(y)-query(x-1));
    41     }
    42     return 0;
    43 }
    View Code

    树状数组,区间修改,区间查询 (http://codevs.cn/problem/1082/

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 inline int read() {
     6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     8 }
     9 
    10 const int N = 200010;
    11 int a[N],b[N];
    12 
    13 struct BIT{
    14     int n;LL c1[N],c2[N];
    15     void update(int p,int v) {
    16         for (int i=p; i<=n; i+=(i&(-i))) c1[i] += v,c2[i] += p*v;
    17     }
    18     LL query(int p) {
    19         LL ans = 0;
    20         for (int i=p; i; i-=(i&(-i))) ans += (p+1)*c1[i]-c2[i];
    21         return ans;
    22     }
    23 }bit;
    24 
    25 int main() {
    26     int n = read(),last = 0;
    27     bit.n = n;
    28     for (int i=1; i<=n; ++i) {
    29         int tmp = read();
    30         a[i] = tmp - last;
    31         last = tmp;
    32     }
    33     for (int i=1; i<=n; ++i) 
    34         bit.update(i,a[i]);
    35         
    36     int m = read();
    37     while (m--) {
    38         int opt = read();
    39         if (opt == 1) {
    40             int l = read(),r = read(),v = read();
    41             bit.update(l,v);
    42             if (r < n) bit.update(r+1,-v);
    43         }
    44         else {
    45             int l = read(),r = read();
    46             printf("%lld
    ",bit.query(r)-bit.query(l-1));
    47         }
    48     }
    49     return 0;
    50 }
    View Code

    树链剖分

     1 void dfs1(int u,int f,int d)    //找重孩子 ,u是当前节点,f节点的父亲,d深度 
     2 {
     3     dep[u] = d;
     4     fa[u] = f;
     5     siz[u] = 1;
     6     for (int i=head[u]; i; i=e[i].nxt)
     7     {
     8         int v = e[i].to;
     9         if (v!=f)
    10         {
    11             dfs1(v,u,d+1);
    12             siz[u] += siz[v];
    13             if (siz[v]>siz[son[u]])//son[]数组,用来保存重儿子
    14                 son[u] = v;
    15         }
    16     }
    17 }
    18 void dfs2(int x)    //找重链 
    19 {
    20     int t = 0;
    21     if (!top[x]) top[x] = x;
    22     for (int i=head[x]; i; i=e[i].nxt)
    23         if (fa[x]!=e[i].to&&siz[t]<siz[e[i].to]) 
    24             t = e[i].to;
    25     if (t) top[t] = top[x], dfs2(t);
    26     for (int i=head[x]; i; i=e[i].nxt)
    27         if(fa[x]!=e[i].to&&t!=e[i].to) dfs2(e[i].to);
    28 }
    29 
    30 /*
    31 siz[]数组,用来保存以x为根的子树节点个数
    32 top[]数组,用来保存当前节点的所在链的顶端节点
    33 son[]数组,用来保存重儿子
    34 dep[]数组,用来保存当前节点的深度
    35 fa[]数组,用来保存当前节点的父亲
    36 */
    View Code

    splay 基本的插入,删除,查询x数的排名,查询排名为x的数,求x的前驱,后继(例题http://www.lydsy.com/JudgeOnline/problem.php?id=3224

      1 #include<cstdio>
      2  
      3 const int N = 100010;
      4 int fa[N],ch[N][2],siz[N],cnt[N],data[N];
      5 int tn,Root;
      6 
      7 inline char nc() {
      8     static char buf[100000],*p1 = buf,*p2 = buf;
      9     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF :*p1++;
     10 }
     11 inline int read() {
     12     int x = 0,f = 1;char ch=nc();
     13     for (; ch<'0'||ch>'9'; ch = nc()) 
     14         if (ch == '-') f = -1;
     15     for (; ch>='0'&&ch<='9'; ch = nc()) 
     16         x = x*10+ch-'0';
     17     return x * f;
     18 }
     19 inline int son(int x) {
     20     return x == ch[fa[x]][1]; // - 
     21 }
     22 inline void pushup(int x) {
     23     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
     24 }
     25 inline void rotate(int x) {
     26     int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b];
     27     if (z) ch[z][c] = x;else Root = x;fa[x] = z; // 调整x的位置
     28     ch[x][!b] = y;fa[y] = x; // 调整y的位置
     29     ch[y][b] = a;if (a) fa[a] = y; // 给y另一个子节点
     30     pushup(y);pushup(x);
     31 }
     32 inline void splay(int x,int rt) {
     33     while (fa[x] != rt) {
     34         int y = fa[x],z = fa[y];
     35         if (z==rt) rotate(x);
     36         else {
     37             if (son(x)==son(y)) rotate(y),rotate(x);
     38             else rotate(x),rotate(x);
     39         }
     40     }
     41 }
     42 inline int getpre(int x) { //得到第一个比x小的数 
     43     int p = Root,ans;
     44     while (p) {
     45         if (x <= data[p]) p = ch[p][0];
     46         else ans = p,p = ch[p][1];
     47     }
     48     return ans;
     49 }
     50 inline int getsuc(int x) { // 得到第一个比x大的数
     51     int p = Root,ans;
     52     while (p) {
     53         if (x >= data[p]) p = ch[p][1];
     54         else ans = p,p = ch[p][0];
     55     }
     56     return ans;
     57 }
     58 inline int getk(int k) { // 得到k的排名
     59     int p = Root,ans = 0;
     60     while (true) {
     61         if (k < data[p]) p = ch[p][0];
     62         else {
     63             ans += (ch[p][0] ? siz[ch[p][0]] : 0);
     64             if (k==data[p]) {
     65                 splay(p,0);return ans+1;
     66             }
     67             ans += cnt[p];
     68             p = ch[p][1];
     69         }
     70     }
     71 }
     72 inline int getkth(int k) { // 得到第k个数
     73     int p = Root;
     74     while (true) {
     75         if (ch[p][0] && k <= siz[ch[p][0]]) p = ch[p][0];
     76         else {
     77             int tmp = (ch[p][0] ? siz[ch[p][0]] : 0) + cnt[p];
     78             if (k <= tmp) return data[p];
     79             k -= tmp; p = ch[p][1];
     80         }
     81     }
     82 }
     83 inline void Insert(int x) { // 插入
     84     if (Root==0) {
     85         ++tn; Root = tn; 
     86         ch[tn][1] = ch[tn][0] = fa[tn] = 0;
     87         siz[tn] = cnt[tn] = 1;data[tn] = x;
     88         return;
     89     }
     90     int p = Root,pa = 0;
     91     while (true) {
     92         if (x==data[p]) {
     93             cnt[p]++;pushup(p);pushup(pa);splay(p,0);break;
     94         }
     95         pa = p;
     96         p = ch[p][x > data[p]];
     97         if (p==0) {
     98             tn++;
     99             ch[tn][1] = ch[tn][0] = 0;siz[tn] = cnt[tn] = 1;
    100             fa[tn] = pa;ch[pa][x > data[pa]] = tn;data[tn] = x; //-
    101             pushup(pa),splay(tn,0);break;
    102         }
    103     }
    104 }
    105 inline void Clear(int x) {
    106     ch[x][0] = ch[x][1] = fa[x] = siz[x] = cnt[x] = data[x] = 0;
    107 }
    108 inline void Delete(int x) { // 删除
    109     getk(x);
    110     if (cnt[Root] > 1) {cnt[Root]--;pushup(Root);return;}
    111     if (!ch[Root][0] && !ch[Root][1]) {Clear(Root);Root = 0;return;}
    112     if (!ch[Root][0]) {
    113         int tmp = Root;Root = ch[Root][1];fa[Root] = 0;Clear(tmp);return;
    114     }
    115     else if (!ch[Root][1]) {
    116         int tmp = Root;Root = ch[Root][0];fa[Root] = 0;Clear(tmp);return;
    117     }
    118     int tmp = Root,pre = ch[Root][0];//可以是getpre(data[Root]);等价于下面的while 
    119     while (ch[pre][1]) pre = ch[pre][1];
    120     splay(pre,0);
    121     ch[Root][1] = ch[tmp][1];
    122     fa[ch[tmp][1]] = Root;
    123     Clear(tmp);
    124     pushup(Root);
    125 }
    126 int main() {
    127     int n = read();
    128     while (n--){
    129         int opt = read(),x = read();
    130         if (opt==1) Insert(x);
    131         else if (opt==2) Delete(x);
    132         else if (opt==3) printf("%d
    ",getk(x));
    133         else if (opt==4) printf("%d
    ",getkth(x));
    134         else if (opt==5) printf("%d
    ",data[getpre(x)]);
    135         else printf("%d
    ",data[getsuc(x)]);
    136     }
    137     return 0;
    138 }
    View Code

    虚树的建立

     1 bool cmp_dfn(int a,int b) {
     2     return dfn[a] < dfn[b];
     3 }
     4 void Insert(int p) {
     5     int x = sk[top], lca = LCA(x, p);
     6     if (lca == x) { sk[++top] = p; return ; }
     7     while (lca != x) {
     8         int y = sk[--top];
     9         if (dfn[y] < dfn[lca]) {
    10             add_edge(lca, x); sk[++top] = lca; 
    11             break;
    12         }
    13         add_edge(y, x); x = y;
    14     }
    15     sk[++top] = p;
    16 }
    17 void build() {
    18     int k = read();
    19     for (int i=1; i<=k; ++i) A[i] = read(); 
    20     sort(A + 1, A + k + 1, cmp_dfn);
    21     top = 0; sk[++top] = 1;
    22     if (A[1] != 1) sk[++top] = A[1];
    23     else sk[++top] = A[2];
    24     for (int i=(A[1]!=1?2:3); i<=k; ++i) Insert(A[i]);
    25     while (--top) add_edge(sk[top], sk[top + 1]);
    26 }
    View Code

    字符串

    kmp模板(例题https://www.luogu.org/problem/show?pid=3375

     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 char a[1000100],b[1010];
     5 int p[1010];     //最长公共前后缀长度 
     6 int s1,s2;
     7 void init()
     8 {
     9     int j = 0;
    10     p[0] = 0;
    11     for (int i=1; i<s2; ++i)
    12     {
    13         while(j>0 && b[i]!=b[j]) j = p[j-1];
    14         if(b[i]==b[j]) j++;
    15         p[i] = j;
    16     }
    17 }
    18 void kmp()
    19 {
    20     int j = 0;
    21     for (int i=0; i<s1; ++i)
    22     {
    23         while(j>0 && a[i]!=b[j]) j = p[j-1];
    24         if(a[i]==b[j]) j++;
    25         if(j==s2) printf("%d
    ",i+1-s2+1); //找到匹配输出i的值,第一个字符是 0,所以加1 
    26     }
    27 }
    28 int main()
    29 {
    30     scanf("%s",a);
    31     scanf("%s",b);
    32     s1 = strlen(a);
    33     s2 = strlen(b);
    34     init();
    35     kmp();
    36     for(int i=0;i<s2;++i)
    37         printf("%d ",p[i]);
    38     return 0;
    39 }
    View Code

    manacher算法,求最长回文串(例题https://www.luogu.org/problem/show?pid=3805

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define MAXN 31000000
     5 using namespace std;
     6 
     7 char s[MAXN],str[MAXN];
     8 int p[MAXN],len;
     9 
    10 void init()
    11 {
    12     len = strlen(str);
    13     s[0] = '#';
    14     for (int i=0; i<len; ++i)
    15     {
    16         s[i<<1|1] = '#';
    17         s[(i+1)<<1] = str[i];
    18     }
    19     s[len<<1|1] = '#';
    20     len = (len<<1|1);
    21 }
    22 int manacher()
    23 {
    24     int mx = 0, id;
    25     for (int i=1; i<=len; ++i)
    26     {
    27         if (mx>i) p[i] = min(p[id<<1-1],mx-i);
    28         else p[i] = 1;
    29         while (s[i+p[i]]==s[i-p[i]]) p[i]++;
    30         if (p[i]+i>mx) 
    31             mx = p[i]+i, id = i;
    32     }
    33     int ans = 0;
    34     for (int i=1; i<len; ++i) ans = max(ans,p[i]);
    35     return ans-1;
    36 }
    37 int main()
    38 {
    39     scanf("%s",str);
    40     init();
    41     printf("%d",manacher());
    42     return 0;
    43 }
    View Code

    trie树,结构体封装函数

     1 struct Trie
     2 {
     3     int ch[MAXN][26];//MAXN=字符集*长度 
     4     int val[MAXN];
     5     int size;
     6     Trie()    //或者:函数Clear()
     7     {
     8         size = 1;
     9         memset(ch,0,sizeof(ch));
    10         memset(val,0,sizeof(val));
    11     }
    12     int id(char c)
    13     {
    14         return c-'a';
    15     }
    16     void Insert(char* s)
    17     {
    18         int u = 0, len = strlen(s);
    19         for (int i=0; i<len; ++i)
    20         {
    21             int c = id(s[i]);
    22             if (!ch[u][c]) ch[u][c] = size++;
    23             u = ch[u][c];
    24             //如果是统计前缀单词个数,在此处上val[u]++;下面的val[u]=1删掉 
    25         }
    26         val[u] = 1;//标记单词是否出现过 
    27     }
    28     bool Find(char* s)
    29     {
    30         int u = 0, len = strlen(s);
    31         for (int i=0; i<len; ++i)
    32         {
    33             int c = id(s[i]);
    34             if (!ch[u][c]) return false;
    35             u = ch[u][c];
    36         }
    37         if (val[u]) return true;//统计前缀单词个数,return val[u]; 
    38         return false; 
    39     }    
    40 }t;
    View Code

    AC自动机模板

     1 //AC自动机 
     2 struct AC_automaton{
     3     int ch[MAXN][26],val[MAXN],last[MAXN],fail[MAXN],size,ret;
     4     void clear()
     5     { 
     6         memset(ch[0],0,sizeof(ch[0]));
     7         memset(val,0,sizeof(val));
     8         memset(fail,0,sizeof(fail));
     9         size = 0;
    10         ret = 0;
    11     }
    12     int idx(char c)
    13     {
    14         return c-'a';
    15     }
    16     void insert(char *s)//插入一个字符串 
    17     {
    18         int u = 0,len = strlen(s);
    19         for (int i=0; i<len; ++i)
    20         {
    21             int c = idx(s[i]);
    22             if (!ch[u][c])
    23             {
    24                 ch[u][c] = ++size;
    25                 val[size] = 0;
    26                 memset(ch[size],0,sizeof(ch[size]));
    27             }
    28             u = ch[u][c];
    29         }
    30         val[u] ++;
    31     }
    32     void getfail()//处理fail指针 
    33     {
    34         queue<int>q;
    35         fail[0] = 0;
    36         for (int c=0; c<26; ++c) 
    37         {
    38             int u = ch[0][c];
    39             if (u) 
    40             {
    41                 fail[u] = 0;q.push(u);last[u] = 0;
    42             }
    43         }
    44         while (!q.empty())
    45         {
    46             int r = q.front();q.pop();
    47             for (int c=0; c<26; ++c)
    48             {
    49                 int u = ch[r][c];
    50                 if (!u)
    51                 {
    52                     ch[r][c] = ch[fail[r]][c];//有这一行就可以减去89行 
    53                     continue;
    54                 }
    55                 q.push(u);
    56                 int v = fail[r];
    57                 while (v && !ch[v][c]) v = fail[v];
    58                 fail[u] = ch[v][c];
    59                 last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
    60             }
    61         }
    62     }
    63     void solve(int j)//可以任意改变的函数,看题目需要什么,这个是处理文本串中有多少个模式串 
    64     {
    65         if (!j) return ;
    66         if (val[j])
    67         {
    68             ret += val[j];
    69             val[j] = 0;
    70         }
    71         solve(last[j]);
    72     }
    73     void find(char *T)//遍历一遍文本串 
    74     {
    75         int j = 0,len = strlen(T);
    76         for (int i=0; i<len; ++i)
    77         {
    78             int c = idx(T[i]);
    79             //while (j && !ch[j][c]) j = fail[j];
    80             j = ch[j][c];
    81             if (val[j]) solve(j);
    82             else if (last[j]) solve(last[j]);
    83         }
    84     }
    85     
    86 }ac;
    View Code

    后缀数组

     1 int s[N];
     2 int t1[N],t2[N],c[N],sa[N],height[N],rank[N];
     3 int n,m = 130,k;
     4 
     5 void get_sa() {
     6     int i,p,*x = t1,*y = t2;
     7     for (i=0; i<m; ++i) c[i] = 0;
     8     for (i=0; i<n; ++i) x[i] = s[i],c[x[i]]++;
     9     for (i=1; i<m; ++i) c[i] += c[i-1];
    10     for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
    11     for (int k=1; k<=n; k<<=1) {
    12         p = 0;
    13         for (i=n-k; i<n; ++i) y[p++] = i;
    14         for (i=0; i<n; ++i) if(sa[i]>=k) y[p++]=sa[i]-k;
    15         for (i=0; i<m; ++i) c[i] = 0;
    16         for (i=0; i<n; ++i) c[ x[y[i]] ]++;
    17         for (i=1; i<m; ++i) c[i] += c[i-1];
    18         for (i=n-1; i>=0; --i) sa[--c[ x[y[i]] ]] = y[i];
    19         swap(x,y);
    20         p = 1;
    21         x[sa[0]] = 0;
    22         for (i=1; i<n; ++i) 
    23             x[sa[i]] = y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k] ? p-1:p++;
    24         if (p>=n) break;
    25         m = p;
    26     }
    27 }
    28 void get_height() {
    29     for (int i=0; i<n; ++i) rank[sa[i]] = i;
    30     int k = 0;
    31     height[0] = 0;
    32     for (int i=0; i<n; ++i) {
    33         if (!rank[i]) continue;
    34         if (k) k--;
    35         int j = sa[rank[i]-1];
    36         while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++;
    37         height[rank[i]] = k;
    38     }
    39 }
    View Code

    Hash

    1 void init() {
    2     mi[0] = 1;
    3     for (int i=1; i<=n; ++i) mi[i] = mi[i - 1] * Base;
    4     for (int i=1; i<=n; ++i) Hash[i] = Hash[i - 1] * Base + (s[i] - 'a' + 1);
    5 }
    6 uLL gethash(int l,int r) {
    7     return Hash[r] - Hash[l] * mi[r - l + 1];
    8 }
    View Code

    计算几何

    Graham求凸包,luogu2742

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cctype>
     6 #include<cmath>
     7 using namespace std;
     8 typedef long long LL;
     9 
    10 double read() {
    11     double x = 0, f = 1, y = 0.1; char ch = getchar();
    12     for (; !isdigit(ch)&&ch!='.'; ch=getchar()) if (ch=='-') f = -1;
    13     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0';
    14     if (ch == '.') ch = getchar();
    15     for (; isdigit(ch); ch=getchar()) x += (ch - '0') * y, y *= 0.1;
    16     return x * f;
    17 }
    18 
    19 const double eps = 1e-8;
    20 
    21 struct Vector{
    22     double x,y;
    23     Vector() {}
    24     Vector(double a,double b) { x = a, y = b; }
    25 };
    26 typedef Vector Point;
    27 Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x, a.y+b.y); }
    28 Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x, a.y-b.y); }
    29 Vector operator * (Vector a,double p) { return Vector(a.x * p, a.y * p); }
    30 Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
    31 bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }
    32 
    33 int dcmp(double x) {
    34     if (fabs(x) <= eps) return 0;
    35     return x > 0 ? x : -x;
    36 }
    37 double cross(Vector a, Vector b) {
    38     return a.x * b.y - a.y * b.x;
    39 }
    40 double len(Vector a) {
    41     return sqrt(a.x * a.x + a.y * a.y);
    42 }
    43 
    44 double X,Y;
    45 bool cmp_angle(Point a,Point b) {
    46     if (atan2(a.y-Y,a.x-X) == atan2(b.y-Y,b.x-X)) return a.x < b.x;
    47     return atan2(a.y-Y,a.x-X) < atan2(b.y-Y,b.x-X);
    48 }
    49 
    50 const int N = 100100;
    51 Point A[N], sk[N];
    52 int n;
    53 
    54 void Graham() {
    55     Y = 1e9;
    56     int t, Top = 0;
    57     for (int i=1; i<=n; ++i) 
    58         if (A[i].y < Y) Y = A[i].y, X = A[i].x, t = i;
    59     swap(A[t],A[1]);
    60     sort(A+2,A+n+1,cmp_angle);
    61     sk[++Top] = A[1];
    62     sk[++Top] = A[2];
    63     for (int i=3; i<=n; ++i) {
    64         // 直线Top-1 -> A[i] 如果在Top-1 -> Top的 外侧,即逆时针旋转过去的,那么Top可以弹出。 
    65         while (Top > 1 && cross(sk[Top]-sk[Top-1],A[i]-sk[Top-1]) < 0) Top--;
    66         sk[++Top] = A[i];
    67     }
    68     double ans = 0;
    69     for (int i=2; i<=Top; ++i) 
    70         ans += len(sk[i] - sk[i-1]);
    71     ans += len(sk[1] - sk[Top]);
    72     printf("%.2lf",ans);
    73 }
    74 
    75 int main() {
    76     cin >> n;
    77     for (int i=1; i<=n; ++i) 
    78         A[i].x = read(), A[i].y = read();
    79     Graham();
    80     return 0;
    81 }
    View Code

    增量排序法求半平面交,poj2451

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<cctype>
      6 #include<cmath>
      7 using namespace std;
      8 typedef long long LL;
      9 
     10 double read() {
     11     double x = 0, f = 1, y = 0.1; char ch = getchar();
     12     for (; !isdigit(ch)&&ch!='.'; ch=getchar()) if (ch=='-') f = -1;
     13     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0';
     14     if (ch == '.') ch = getchar();
     15     for (; isdigit(ch); ch=getchar()) x += (ch - '0') * y, y *= 0.1;
     16     return x * f;
     17 }
     18 
     19 const double eps = 1e-8;
     20 
     21 struct Vector{
     22     double x,y;
     23     Vector() {}
     24     Vector(double a,double b) { x = a, y = b; }
     25 };
     26 typedef Vector Point;
     27 Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x, a.y+b.y); }
     28 Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x, a.y-b.y); }
     29 Vector operator * (Vector a,double p) { return Vector(a.x * p, a.y * p); }
     30 Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
     31 bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }
     32 
     33 struct Line{
     34     Point s, t;
     35     double angle;
     36     Line () {}
     37     Line (Point a,Point b) {s = a, t = b, angle = atan2(b.y - a.y, b.x - a.x);}
     38     
     39 };
     40 
     41 int dcmp(double x) {
     42     if (fabs(x) <= eps) return 0;
     43     return x > 0 ? 1 : -1;
     44 }
     45 double cross(Vector a, Vector b) {
     46     return a.x * b.y - a.y * b.x;
     47 }
     48 Point jiaodian(Line a, Line b) {
     49     Point A = a.s, B = a.t, C = b.s, D = b.t;
     50     double t1 = cross(D - A, B - A), t2 = cross(B - A, C - A);
     51     double t = t1 / (t1 + t2);
     52     return C * t + D * (1 - t);
     53 }
     54 
     55 const int N = 20010;
     56 
     57 Point A[N];
     58 Line seg[N];
     59 int q[N];
     60 int n,tot;
     61 
     62 bool cmp_angle(Line A,Line B) { // 按极角排序,小的在前,极角相等的话,左边的在前 
     63     double d = dcmp(A.angle - B.angle);
     64     if (!d) return dcmp(cross(B.s - A.s, B.t - A.s)) > 0;
     65     return d < 0;
     66 }
     67 bool judge(Line C,Line A, Line B) { // 判断AB的交点是否在C的左边 
     68     Point p = jiaodian(A, B);
     69     return dcmp(cross(C.s - p, C.t - p)) < 0; // 在C的右边返回true 
     70 }
     71 
     72 void solve() {
     73     sort(seg+1, seg+n+1, cmp_angle);
     74     int j = 1;
     75     for (int i=2; i<=n; ++i) // 将极角相同的只保留最左边的 
     76         if (dcmp(seg[i].angle - seg[j].angle) > 0) seg[++j] = seg[i];
     77     n = j;
     78     q[1] = 1, q[2] = 2;
     79     int L = 1, R = 2;
     80     for (int i=3; i<=n; ++i) {
     81         while (L < R && judge(seg[i], seg[q[R]], seg[q[R-1]])) R --; // 栈中最后两个线段的交点在这条的右边 
     82         while (L < R && judge(seg[i], seg[q[L]], seg[q[L+1]])) L ++; // 由于是凸多边形,新加入的线段可能转回来,把起点挡在右边 
     83         q[++R] = i;
     84     }
     85     while (L < R && judge(seg[q[L]], seg[q[R]], seg[q[R-1]])) R --;
     86     while (L < R && judge(seg[q[L]], seg[q[L]], seg[q[L+1]])) L ++;
     87     q[++R] = q[L];
     88     tot = 0;
     89     for (int i=L; i<R; ++i) 
     90         A[++tot] = jiaodian(seg[q[i]], seg[q[i+1]]); // 求交点 
     91 }
     92 
     93 double Area() {
     94     double ans = 0;
     95     for (int i=2; i<tot; ++i) 
     96         ans += cross(A[i]-A[1],A[i+1]-A[1]);
     97     return ans / 2.0;
     98 } 
     99 
    100 int main() {    
    101     while (~scanf("%d",&n)) {
    102         for (int i=1; i<=n; ++i) {
    103             double a1 = read(), b1 = read(), a2 = read(), b2 = read();
    104             seg[i] = Line(Point(a1, b1), Point(a2, b2));
    105         }
    106         seg[++n] = Line(Point(0, 0), Point(10000, 0));
    107         seg[++n] = Line(Point(10000, 0), Point(10000, 10000));
    108         seg[++n] = Line(Point(10000, 10000), Point(0, 10000));
    109         seg[++n] = Line(Point(0, 10000), Point(0, 0));
    110         solve();
    111         printf("%.1lf
    ",Area());
    112     }
    113     return 0;
    114 }
    View Code

    旋转卡壳,求凸包直径,poj2187

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cctype>
     6 #include<cmath>
     7 using namespace std;
     8 typedef long long LL;
     9 
    10 inline int read() {
    11     int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch=getchar()) if (ch=='-') f = -1;
    12     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0'; return x * f;
    13 }
    14 
    15 struct Vector{
    16     int x,y;
    17     Vector() {}
    18     Vector(int a,int b) { x = a, y = b; }
    19 };
    20 typedef Vector Point;
    21 Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x, a.y+b.y); }
    22 Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x, a.y-b.y); }
    23 Vector operator * (Vector a,double p) { return Vector(a.x * p, a.y * p); }
    24 Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
    25 bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }
    26 
    27 int len(Vector a) {
    28     return a.x * a.x + a.y * a.y;
    29 }
    30 int cross(Vector a, Vector b) {
    31     return a.x * b.y - a.y * b.x;
    32 }
    33 
    34 const int N = 50010;
    35 Point A[N], sk[N];
    36 double X,Y;
    37 int n, Top;
    38 
    39 bool cmp_angle(Point a,Point b) { // --- 
    40     int t = cross(a - A[1], b - A[1]);
    41     if (t > 0 || (t == 0 && len(a - A[1]) > len(b - A[1]))) return true;
    42     return false;
    43 }
    44 
    45 void Graham() {
    46     int t; Top = 0; Y = 1e9;
    47     for (int i=1; i<=n; ++i) 
    48         if (A[i].y < Y || (A[i].y == Y && A[i].x < X)) Y = A[i].y, X = A[i].x, t = i;
    49     swap(A[t], A[1]);
    50     sort(A+2, A+n+1, cmp_angle);
    51     sk[++Top] = A[1];
    52     sk[++Top] = A[2];
    53     for (int i=3; i<=n; ++i) {
    54         while (Top > 1 && cross(sk[Top] - sk[Top-1], A[i] - sk[Top-1]) < 0) Top --;
    55         sk[++Top] = A[i];
    56     }
    57 }
    58 int Area(Point a,Point b,Point c) {
    59     return cross(b - a, c - a);
    60 }
    61 void RC() {
    62     sk[++Top] = sk[1];
    63     int p = 2;
    64     int ans = len(sk[2] - sk[1]);
    65     for (int i=1; i<Top; ++i) {
    66         while (Area(sk[i],sk[i+1],sk[p+1]) > Area(sk[i],sk[i+1],sk[p])) p = p % Top + 1;
    67         ans = max(ans, max(len(sk[p] - sk[i]), len(sk[p] - sk[i+1])));
    68     }
    69     printf("%d
    ",ans);
    70 }
    71 int main() {
    72     while (~scanf("%d",&n)) {
    73         for (int i=1; i<=n; ++i) 
    74             A[i].x = read(), A[i].y = read();
    75         Graham();
    76         RC();
    77     }
    78     return 0;
    79 }
    View Code

    其他

    二分答案

    a最小值最大

     1 //最小值最大
     2 int l = min_ans, r = max_ans;  
     3 while (l < r) 
     4 {  
     5     int mid = (l+r+1)/2;   //+1避免 r==l+1 时mid一直等于l,从而死循环  
     6     if (ok(mid))    //符合条件返回True  
     7         l = mid;  
     8     else  
     9         r = mid - 1;  
    10 }  
    View Code

    b最大值最小

     1 //最大值最小
     2 int l = min_ans, r = max_ans;  
     3 while (l < r) 
     4 {  
     5     int mid = (l+r)/2;  
     6     if (ok(mid))    //符合条件返回True  
     7         r = mid;  
     8     else  
     9         l = mid + 1;  
    10 } 
    View Code

    归并排序模板(例题https://www.luogu.org/problem/show?pid=1177

     1 #include<cstdio>
     2 
     3 int n,ans;
     4 int a[500100],b[500100];    //a原数组,b暂存数组 
     5 
     6 void merge_sort(int l,int r)    //归并 
     7 {
     8     if (l==r) return ;    //一个数不用排序 
     9     int m = (l+r)>>1;
    10     merge_sort(l,m);    //排序左边 
    11     merge_sort(m+1,r);    //排序右边 
    12     int i = l, j = m+1, k = l ;    //i左边最小的位置,j右边最小的位置 
    13     while (i<=m && j<=r)
    14         if (a[i]<=a[j]) b[k++] = a[i++];
    15         else b[k++] = a[j++];
    16     while (i<=m) b[k++] = a[i++];    //加入左边剩余的数 
    17     while (j<=r) b[k++] = a[j++];    //加入右边剩余的数
    18     for (i=l; i<=r; ++i) a[i] = b[i];    //从暂存数组中赋值 
    19 }
    20 
    21 int main()
    22 {
    23     scanf("%d",&n);
    24     for (int i=1; i<=n; ++i)
    25         scanf("%d",&a[i]);
    26     merge_sort(1,n);
    27     for (int i=1; i<=n; ++i)
    28         printf("%d ",a[i]);
    29     return 0;
    30 }
    View Code

    归并排序求逆序对(例题https://www.luogu.org/problem/show?pid=1908

     1 #include<cstdio>
     2 
     3 int n,ans;
     4 int a[500100],b[500100];    //a原数组,b暂存数组 
     5 
     6 void merge_sort(int l,int r)    //归并 
     7 {
     8     if (l==r) return ;    //一个数不用排序 
     9     int m = (l+r)>>1;
    10     merge_sort(l,m);    //排序左边 
    11     merge_sort(m+1,r);    //排序右边 
    12     int i = l, j = m+1, k = l ;    //i左边最小的位置,j右边最小的位置 
    13     while (i<=m && j<=r)
    14         if (a[i]<=a[j]) b[k++] = a[i++];
    15         else ans += m-i+1, b[k++] = a[j++];    //加入右半段时,逆序对数增加 
    16     while (i<=m) b[k++] = a[i++];    //加入左边剩余的数 
    17     while (j<=r) b[k++] = a[j++];    //加入右边剩余的数
    18     for (i=l; i<=r; ++i) a[i] = b[i];    //从暂存数组中赋值 
    19 }
    20 
    21 int main()
    22 {
    23     scanf("%d",&n);
    24     for (int i=1; i<=n; ++i)
    25         scanf("%d",&a[i]);
    26     merge_sort(1,n);
    27     printf("%d",ans);
    28     return 0;
    29 }
    View Code

    树状数组求逆序对

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 
     8 using namespace std;
     9 
    10 const int N = 100010;
    11 
    12 struct Node{
    13     int val,pos;
    14     bool operator < (const Node &a) const {
    15         return val > a.val;
    16     }
    17 }a[N];
    18 int sum[N],n;
    19 
    20 inline int read() {
    21     int x = 0,f = 1;char ch=getchar();
    22     for (; !isdigit(ch); ch=getchar()) if(ch=='-')f=-1;
    23     for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
    24     return x*f;
    25 }
    26 void update(int p,int x) {
    27     for (; p<=n; p+=p&(-p)) sum[p] += x;
    28 }
    29 int query(int p) {
    30     int ans = 0;
    31     for (; p>=1; p-=p&(-p)) ans += sum[p];
    32     return ans;
    33 }
    34 int main() {
    35     n = read();
    36     for (int i=1; i<=n; ++i) 
    37         a[i].val = read(),a[i].pos = i;
    38     sort(a+1,a+n+1);
    39     int ans = 0;
    40     for (int i=1; i<=n; ++i) {
    41         ans += query(a[i].pos-1);
    42         update(a[i].pos,1);
    43     }
    44     cout << ans;
    45     return 0;
    46 }
    View Code

     二分查找一个数,必须要排好序

     1 int binary_search(int x,int y,int c)
     2 {
     3     int l,r,mid;
     4     l = x; 
     5     r = y;
     6     while (l<r)
     7     {
     8         mid = (l+r)>>1;
     9         if (c<=a[mid]) r = mid;
    10         else l = mid+1;
    11     }
    12     return l;
    13 }
    14 /*------------------------------------*/
    15 int find(int l,int r,int x)
    16 {
    17     while (l<=r)
    18     {
    19         int mid = (l+r)>>1;
    20         if (a[mid]<=x) l = mid+1;
    21         else r = mid-1;
    22     }
    23     return l;
    24 }
    二分查找

    等价于(stl):

    1 lower_bound(a+x,a+y+1,c)-a; 
    lower_bound

     快速排序

     1 void qsort(int l,int r)
     2 {
     3     int i = l,j = r;
     4     int mid = a[(l+r)>>1];
     5     while (i<=j)
     6     {
     7         while (a[i]<mid) i++;
     8         while (a[j]>mid) j--;
     9         if (i<=j)
    10         {
    11             int t = a[i]; a[i] = a[j]; a[j] = t;
    12             i++; j--;
    13         }
    14     }
    15     if (i<r) qsort(i,r);
    16     if (l<j) qsort(l,j);
    17 }
    快排

    快速排序求第k大的数

     1 int qsort(int *a,int l,int r)
     2 {
     3     int tmp = a[l],pos = l;
     4     int i = l, j = r;
     5     while (i<j)
     6     {
     7         while (i<j&&a[j]>tmp) j--;
     8         if (i<j)
     9         {
    10             a[pos] = a[j];
    11             pos = j;
    12         }
    13         while (i<j&&a[i]<tmp) i++;
    14         if (i<j)
    15         {
    16             a[pos] = a[i];
    17             pos = i;
    18         }
    19     }
    20     a[pos] = tmp;
    21     return pos;
    22 }
    23 int findkth(int *a,int n,int k)
    24 {
    25     int l = 0,r = n-1;
    26     while (1)
    27     {
    28         int pos = qsort(a,l,r);
    29         if (pos==n-k) return a[pos];
    30         else if (pos<n-k) l = pos+1;
    31         else r = pos-1;
    32     }
    33 }
    快速排序求第k大的数

    dfs序

     1 void dfs(int u,int fa) {
     2     q[++tot] = u;
     3     L[u] = tot;
     4     for (int i=head[u]; i; i=e[i].nxt) {
     5         int v = e[i].to;
     6         if (v==fa) continue;
     7         dfs(v,u);
     8     }
     9     R[u] = tot;
    10 }
    View Code

    生成下一个(前一个)排列

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<string>
     4  
     5 using namespace std;
     6  
     7 int main()
     8 {
     9     string s;
    10     cin>>s; // 包括string类型,vector,还有数组(指针左闭右开) 
    11     sort(str.begin(), str.end());
    12     cout<<str<<endl;
    13     while (next_permutation(str.begin(), str.end())) { // 返回bool类型, 
    14         cout << str << endl;
    15     }
    16     return 0;
    17 }
    18 // 相应的 前一个排列 pre_permutation 
    View Code

     三分查找(求凸函数最大值的位置)

    1 double search() {
    2     while (r - l >= eps) {
    3         lmid = (l + r) / 2.0;
    4         rmid = (lmid + r) / 2.0;
    5         if (f(lmid) >= f(rmid)) r = rmid;
    6         else l = lmid;
    7     }
    8     return l;
    9 }
    View Code

    集合hash,判断两个集合是否一样

     1 uLL getkey() {
     2     uLL a = (rand() << 15) | rand();
     3     uLL b = (rand() << 15) | rand();
     4     return a * b;    
     5 } 
     6 uLL init() {
     7     for (int i=1; i<=MAX_NUM; ++i) Key[i] = init(); // 数字i的key 
     8 }
     9 int gethash(int *A) {
    10     uLL ans = 0;
    11     for (int i=1; i<=n; ++i) ans = ans ^ Key[A[i]];
    12     return ans;
    13 }
    View Code

      

    ——————————————————————

  • 相关阅读:
    【SAS BASE】PROC TABULATE(输出更加精美的tabulate报告)
    【SAS BASE】PROC FREQ
    【SAS BASE】PROC MEAS
    【SAS BASE】利用FILE语句和PUT语句输出简单报告
    表单验证类:jquery validate和nice Validator
    手机自适应
    微信公众号支付H5-java版代码
    php ueditor 后台配置项返回格式出错,上传功能将不能正常使用!
    html菜单三条横线
    thinkPHP更新数据库没有响应 setInc save setFiled
  • 原文地址:https://www.cnblogs.com/mjtcn/p/6912995.html
Copyright © 2020-2023  润新知