• noip 考点


    数据结构:
    并查集模板
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 const int N=10005;
     7 int fa[N],n,m;
     8 int find(int x)
     9 {
    10     if(x==fa[x])
    11         return x;
    12     else
    13         return fa[x]=find(fa[x]);
    14 }
    15 int main()
    16 {
    17     scanf("%d %d",&n,&m);
    18     for(int i=1;i<=n;i++)
    19         fa[i]=i;
    20     for(int i=1;i<=m;i++)
    21     {
    22         int x,y,z;
    23         scanf("%d %d %d",&x,&y,&z);
    24         if(x==1)
    25         {
    26             int x1=find(y),x2=find(z);
    27             if(x1!=x2)
    28             {
    29                 fa[x1]=x2;
    30             }
    31         }
    32         else
    33         {
    34             int x1=find(y),x2=find(z);
    35             if(x1==x2)
    36             {
    37                 printf("Y
    ");
    38             }
    39             else
    40             {
    41                 printf("N
    ");
    42             }
    43         }
    44     }
    45     return 0;
    46 }
    带权并查集 :扩展域(食物链,石头剪刀布 poj 2912),size(银河英雄传说);
     
    食物链代码如下
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 const int N=50010,M=100010;
     7 int fa[N],d[N];
     8 int n,m;
     9 
    10 int find(int x)
    11 {
    12     if (fa[x]!=x)
    13     {
    14       int temp=fa[x];
    15       fa[x]=find(temp);
    16       d[x]=(d[x]+d[temp])%3;//推导不会,好像是找规律
    17     }
    18     return fa[x];
    19 }
    20 int main()
    21 {
    22     scanf("%d%d",&n,&m);
    23     int cnt=0;
    24     for (int i=1;i<=n;i++) 
    25         fa[i]=i,d[i]=0;
    26     for (int i=1;i<=m;i++)
    27     {
    28         int dd,x,y;
    29         scanf("%d %d %d",&dd,&x,&y);
    30         if (x>n || y>n || (dd==2 && x==y))
    31         {
    32             cnt++;
    33             continue;
    34         }
    35         dd--;
    36         int x1=find(x),x2=find(y);
    37         if (x1!=x2)
    38         {
    39             fa[x1]=x2;
    40             d[x1]=(d[y]-d[x]+dd+3)%3;
    41         }
    42         else if((d[x]-d[y]+3)%3!=dd) 
    43             cnt++;
    44     }
    45     printf("%d
    ",cnt);
    46     return 0;
    47 }
    石头剪刀布的代码如下(其实与食物链几乎一样)
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 const int N=10005;
     7 int x[N],y[N],fa[N],d[N];
     8 char ch[N];
     9 int n,m;
    10 void init()
    11 {
    12     for(int i=0;i<n;i++)
    13         fa[i]=i,d[i]=0;
    14 }
    15 int find(int x)
    16 {
    17     if(x==fa[x])
    18         return x;
    19     int temp=fa[x];
    20     fa[x]=find(temp);
    21     d[x]=(d[x]+d[temp])%3;
    22     return fa[x];
    23 }
    24 bool merge(int x,int y,int z)
    25 {
    26     int x1=find(x),x2=find(y);
    27     if(x1!=x2)
    28     {
    29         fa[x2]=x1;
    30         d[x2]=(d[x]-d[y]+z+3)%3;
    31     }
    32     else if(x1==x2)
    33     {
    34         if((d[y]-d[x]+3)%3!=z)
    35             return 1;
    36     }
    37     return 0;
    38 }
    39 int main()
    40 {
    41     while(scanf("%d %d",&n,&m)!=EOF)
    42     {
    43         memset(x,0,sizeof(x));
    44         memset(y,0,sizeof(y));
    45         memset(ch,0,sizeof(ch)); 
    46         for(int i=1;i<=m;i++)
    47             scanf("%d %c %d",&x[i],&ch[i],&y[i]);
    48         int k,tot=0,judge=0,line=0;
    49         for(int i=0;i<n;i++)
    50         {
    51             init();
    52             bool flag=true;
    53             for(int j=1;j<=m;j++)
    54             {
    55                 if(x[j]==i || y[j]==i)
    56                     continue;
    57                 if(ch[j]=='=')
    58                     k=0;
    59                 else if(ch[j]=='>')
    60                     k=1;
    61                 else if(ch[j]=='<')
    62                     k=2;
    63                 if(merge(x[j],y[j],k))
    64                 {
    65                     line=max(j,line);
    66                     flag=false;
    67                     break;
    68                 }
    69             }
    70             if(flag)
    71             {
    72                 tot++;
    73                 judge=i;
    74             }
    75         }
    76         if(tot==0)
    77             printf("Impossible
    ");
    78         else if(tot>1)
    79             printf("Can not determine
    ");
    80         else
    81             printf("Player %d can be determined to be the judge after %d lines
    ",judge,line);
    82     }
    83 }

    银河英雄传说代码

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 const int N=500005;
     7 int fa[N],deep[N],size[N],T;
     8 int find(int x)
     9 {
    10     if(fa[x]==x)
    11         return x;
    12     else
    13     {
    14         int temp=fa[x];
    15         fa[x]=find(temp);
    16         deep[x]+=deep[temp];
    17         return fa[x];
    18     }
    19 }
    20 void merge(int x,int y)
    21 {
    22     int x1=find(x),x2=find(y);
    23     if(x1!=x2)
    24     {
    25         fa[x1]=x2;
    26         deep[x1]=size[x2];
    27         size[x2]+=size[x1];//别敲反了
    28     }
    29 }
    30 void query(int x,int y)
    31 {
    32     int x1=find(x),x2=find(y);
    33     if(x1==x2)
    34     {
    35         printf("%d
    ",abs(deep[x]-deep[y])-1);
    36     }
    37     else
    38     {
    39         printf("-1
    ");
    40     }
    41 }
    42 int main()
    43 {
    44     scanf("%d",&T);
    45     for(int i=1;i<N;i++)
    46         fa[i]=i,size[i]=1;
    47     while(T--)
    48     {
    49         int x,y;
    50         char ch[5];
    51         scanf("%s %d %d",ch,&x,&y);
    52         if(ch[0]=='M')
    53         {
    54             merge(x,y);
    55         }
    56         else
    57         {
    58             query(x,y);
    59         }
    60     }
    61 }   
    树状数组:求和,(异或和),二维;
     
    树状数组1
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 using namespace std;
     7 const int N=5000005;
     8 int n,m,c[N];
     9 int lowbit(int x)
    10 {
    11     return x&(-x);
    12 }
    13 void add(int x,int num)
    14 {
    15     while(x<=n)
    16     {
    17         c[x]+=num;
    18         x+=lowbit(x);
    19     }
    20 }
    21 int get_sum(int x)
    22 {
    23     int sum=0;
    24     while(x)
    25     {
    26         sum+=c[x];
    27         x-=lowbit(x);
    28     }
    29     return sum;
    30 }
    31 int main()
    32 {
    33     scanf("%d %d",&n,&m);
    34     for(int i=1;i<=n;i++)
    35     {
    36         int x;
    37         scanf("%d",&x);
    38         add(i,x);
    39     }
    40     for(int i=1;i<=m;i++)
    41     {
    42         int opt,x,y;
    43         scanf("%d %d %d",&opt,&x,&y);
    44         if(opt==1)
    45         {
    46             add(x,y);
    47         }
    48         else
    49         {
    50             printf("%d
    ",get_sum(y)-get_sum(x-1));
    51         }
    52     }
    53 }

    树状数组2

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cmath>
     7 using namespace std;
     8 const int N=5000005;
     9 int n,m,d[N],c[N];
    10 int lowbit(int x)
    11 {
    12     return x&(-x);
    13 }
    14 void add(int x,int num)
    15 {
    16     while(x<=n)
    17     {
    18         c[x]+=num;
    19         x+=lowbit(x);
    20     }
    21 }
    22 int query(int x)
    23 {
    24     int sum=0;
    25     while(x)
    26     {
    27         sum+=c[x];
    28         x-=lowbit(x);
    29     }
    30     return sum;
    31 }
    32 int main()
    33 {
    34     scanf("%d %d",&n,&m);
    35     for(int i=1;i<=n;i++)
    36         scanf("%d",&d[i]);
    37     for(int i=1;i<=m;i++)
    38     {
    39         int opt;
    40         scanf("%d",&opt);
    41         if(opt==1)
    42         {
    43             int x,y,z;
    44             scanf("%d %d %d",&x,&y,&z);
    45             add(x,z);
    46             add(y+1,-z);
    47         }
    48         else
    49         {
    50             int x;
    51             scanf("%d",&x);
    52             printf("%d
    ",query(x)-query(0)+d[x]);
    53         }
    54     }
    55 }
    二维树状数组(上帝造题的7分钟)开o2才过的
    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    using namespace std;
    const int N=10005;
    int c[N][N],cx[N][N],cy[N][N],cxy[N][N];
    int m,n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int g[][N],int x,int y,int deta)
    {
        for(int i=x; i<=n; i=i+lowbit(i))
            for(int j=y; j<=m; j=j+lowbit(j))
                g[i][j]+=deta;
    }
    int sum(int g[][N],int x,int y)
    {
        int sum=0;
        for(int i=x; i; i-=lowbit(i))
            for(int j=y; j; j-=lowbit(j))
                sum=sum+g[i][j];
        return sum;
    }
    void Add(int x,int y,int deta)
    {
        add(c,x,y,deta);
        add(cx,x,y,x*deta);
        add(cy,x,y,y*deta);
        add(cxy,x,y,x*y*deta);
    }
    int Sum(int x,int y)
    {
        return (x*y+x+y+1)*sum(c,x,y)-(y+1)*sum(cx,x,y)-(x+1)*sum(cy,x,y)+sum(cxy,x,y);
    }
    int main()
    {
        char cc;
        scanf("%c %d %d",&c,&n,&m);
        char ch;
        while(~scanf("
    %c",&ch))
        {
            if(ch=='L')
            {
                int x1,y1,x2,y2,deta;
                scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&deta);
                Add(x1,y1,deta);
                Add(x2+1,y1,-deta);
                Add(x1,y2+1,-deta);
                Add(x2+1,y2+1,deta);
            }
            else
            {
                int a,b,c,d;
                scanf("%d %d %d %d",&a,&b,&c,&d);
                printf("%d
    ",Sum(c,d)-Sum(c,b-1)-Sum(a-1,d)+Sum(a-1,b-1));
            }
        }
        return 0;
    }

    树状数组求逆序对

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <map>
     5 #include <string>
     6 using namespace std;
     7 const int N=100005;
     8 typedef long long ll;
     9 map < string , ll > mp;
    10 ll d[N],n,tot;
    11 char ch[10];
    12 ll lowbit(ll x)
    13 {
    14     return x&(-x);
    15 }
    16 void add(ll x)
    17 {
    18     while(x<=n)
    19     {
    20         d[x]++;
    21         x+=lowbit(x);
    22     }
    23 }
    24 ll get(ll x)
    25 {
    26     ll sum=0;
    27     while(x)
    28     {
    29         sum+=d[x];
    30         x-=lowbit(x);
    31     }
    32     return sum;
    33 }
    34 int main()
    35 {
    36     scanf("%lld",&n);
    37     for(ll i=1;i<=n;i++)
    38     {
    39         scanf("%s",ch);
    40         mp[ch]=++tot;
    41     }
    42     ll ans=0;
    43     for(ll i=1;i<=n;i++)
    44     {
    45         scanf("%s",ch);
    46         ll p=mp[ch];
    47         ans+=get(n)-get(p-1);
    48         add(p);
    49     }
    50     printf("%lld
    ",ans);
    51 }
    线段树:前缀和,平方和,状压,权值;
     
    线段树板子1
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 using namespace std;
     5 typedef long long ll;
     6 struct node
     7 {
     8     ll l,r,sum,lazy;
     9 }tree[400005];
    10 ll n,m,d[100005];
    11 void push_up(ll root)
    12 {
    13     tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
    14 }
    15 void push_down(ll root,ll l,ll r)
    16 {
    17     tree[root<<1].lazy+=tree[root].lazy;
    18     tree[root<<1|1].lazy+=tree[root].lazy;
    19     tree[root<<1].sum+=l*tree[root].lazy;
    20     tree[root<<1|1].sum+=r*tree[root].lazy;
    21     tree[root].lazy=0;
    22 }
    23 void build_tree(ll root,ll l,ll r)
    24 {
    25     if(l==r)
    26     {
    27         tree[root].l=l,tree[root].r=r;
    28         tree[root].sum=d[l];
    29         //tree[root].lazy=-1;
    30         return ;
    31     }
    32     tree[root].l=l,tree[root].r=r;
    33     //tree[root].lazy=-1;
    34     ll mid=(l+r)/2;
    35     build_tree(root<<1,l,mid);
    36     build_tree(root<<1|1,mid+1,r);
    37     push_up(root);
    38 }
    39 void update(ll root,ll l,ll r,ll left,ll right,ll num)
    40 {
    41     if(left<=l && right>=r)
    42     {
    43         tree[root].sum+=(r-l+1)*num;
    44         tree[root].lazy+=num;
    45         return ;
    46     }
    47     ll mid=(l+r)/2;
    48     push_down(root,mid-l+1,r-mid);
    49     if(left<=mid)
    50         update(root<<1,l,mid,left,right,num);
    51     if(mid<right)
    52         update(root<<1|1,mid+1,r,left,right,num);
    53     push_up(root);
    54 }
    55 ll query(ll root,ll l,ll r,ll left,ll right)
    56 {
    57     ll ans=0;
    58     if(left<=l && right>=r)
    59     {
    60         return tree[root].sum;
    61     }
    62     ll mid=(l+r)/2;
    63     push_down(root,mid-l+1,r-mid);
    64     if(left<=mid)
    65         ans+=query(root<<1,l,mid,left,right);
    66     if(mid<right)
    67         ans+=query(root<<1|1,mid+1,r,left,right);
    68     return ans;
    69 }
    70 int main()
    71 {
    72     scanf("%lld %lld",&n,&m);
    73     for(ll i=1;i<=n;i++)
    74         scanf("%lld",&d[i]);
    75     build_tree(1,1,n);
    76     for(ll i=1;i<=m;i++)
    77     {
    78         ll opt,x,y,z;
    79         scanf("%lld %lld %lld",&opt,&x,&y);
    80         if(opt==1)
    81         {
    82             scanf("%lld",&z);
    83             update(1,1,n,x,y,z);
    84         }
    85         else
    86         {
    87             printf("%lld
    ",query(1,1,n,x,y));
    88         }
    89     }
    90 }

    线段树板子2

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <iostream>
      4 using namespace std;
      5 typedef long long ll;
      6 struct node
      7 {
      8     ll l,r,sum,lazyj,lazyc;
      9 }tree[400005];
     10 ll n,m,p,d[100005];
     11 void push_up(ll root)
     12 {
     13     tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
     14 }
     15 void push_down(ll root,ll l,ll r)
     16 {    
     17     tree[root<<1].sum=(tree[root<<1].sum*tree[root].lazyc+tree[root].lazyj*l)%p;
     18     tree[root<<1|1].sum=(tree[root<<1|1].sum*tree[root].lazyc+tree[root].lazyj*r)%p;
     19     tree[root<<1].lazyc=tree[root].lazyc*tree[root<<1].lazyc%p;
     20     tree[root<<1|1].lazyc=tree[root].lazyc*tree[root<<1|1].lazyc%p;
     21     tree[root<<1].lazyj=(tree[root].lazyj+tree[root].lazyc*tree[root<<1].lazyj)%p;
     22     tree[root<<1|1].lazyj=(tree[root].lazyj+tree[root].lazyc*tree[root<<1|1].lazyj)%p;
     23     tree[root].lazyj=0; 
     24     tree[root].lazyc=1;
     25 }
     26 void build_tree(ll root,ll l,ll r)
     27 {    
     28     tree[root].l=l,tree[root].r=r;
     29     tree[root].lazyc=1;
     30     if(l==r)
     31     {
     32         tree[root].l=l,tree[root].r=r;
     33         tree[root].sum=d[l];
     34         return ;
     35     }
     36     ll mid=(l+r)/2;
     37     build_tree(root<<1,l,mid);
     38     build_tree(root<<1|1,mid+1,r);
     39     push_up(root);
     40 }
     41 void update(ll root,ll l,ll r,ll left,ll right,ll num,bool flag)
     42 {
     43     if(flag)
     44     {
     45         if(left<=l && right>=r)
     46         {
     47             tree[root].lazyc=num*tree[root].lazyc%p;
     48             tree[root].lazyj=num*tree[root].lazyj%p;
     49             tree[root].sum=num*tree[root].sum%p;
     50             return ;
     51         }
     52         ll mid=(l+r)/2;
     53         push_down(root,mid-l+1,r-mid);
     54         if(left<=mid)
     55             update(root<<1,l,mid,left,right,num,flag);
     56         if(mid<right)
     57             update(root<<1|1,mid+1,r,left,right,num,flag);
     58         push_up(root);
     59     }
     60     else
     61     {
     62         if(left<=l && right>=r)
     63         {
     64             tree[root].sum=(tree[root].sum+(r-l+1)*num)%p;
     65             tree[root].lazyj+=num;
     66             return ;
     67         }
     68         ll mid=(l+r)/2;
     69         push_down(root,mid-l+1,r-mid);
     70         if(left<=mid)
     71             update(root<<1,l,mid,left,right,num,flag);
     72         if(mid<right)
     73             update(root<<1|1,mid+1,r,left,right,num,flag);
     74         push_up(root);
     75     }  
     76 }
     77 ll query(ll root,ll l,ll r,ll left,ll right)
     78 {
     79     ll ans=0;
     80     if(left<=l && right>=r)
     81     {
     82         return tree[root].sum;
     83     }
     84     ll mid=(l+r)/2;
     85     push_down(root,mid-l+1,r-mid);
     86     if(left<=mid)
     87         ans=(ans+query(root<<1,l,mid,left,right))%p;
     88     if(mid<right)
     89         ans=(ans+query(root<<1|1,mid+1,r,left,right))%p;
     90     return ans%p;
     91 }
     92 int main()
     93 {
     94     scanf("%lld %lld %lld",&n,&m,&p);
     95     for(ll i=1;i<=n;i++)
     96         scanf("%lld",&d[i]);
     97     build_tree(1,1,n);
     98     for(ll i=1;i<=m;i++)
     99     {
    100         ll opt,x,y,z;
    101         scanf("%lld %lld %lld",&opt,&x,&y);
    102         if(opt==1)
    103         {
    104             scanf("%lld",&z);
    105             update(1,1,n,x,y,z,1);
    106         }
    107         else if(opt==2)
    108         {
    109             scanf("%lld",&z);
    110             update(1,1,n,x,y,z,0);
    111         }
    112         else if(opt==3)
    113         {
    114             printf("%lld
    ",query(1,1,n,x,y)%p);
    115         }
    116     }
    117 }
     
     
    线段树状压 poj 2777
      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <iostream>
      6 using namespace std;
      7 const int N=100005; 
      8 struct node
      9 {
     10     int l,r,v,lazy;
     11 }tree[N*4];
     12 int n,t,q,x,y,z;
     13 char ch;
     14 int cnt(int x)
     15 {
     16     int ans=0;
     17     while(x)
     18     {
     19         if((x&1)==1)
     20             ans++;
     21         x>>=1;
     22     }
     23     return ans;
     24 }
     25 void push_up(int root)
     26 {
     27     tree[root].v=(tree[root<<1].v|tree[root<<1|1].v);
     28 }
     29 void push_down(int root)
     30 {
     31     if(tree[root].lazy)
     32     {
     33         tree[root<<1].v=tree[root].lazy;
     34         tree[root<<1|1].v=tree[root].lazy;
     35         tree[root<<1].lazy=tree[root].lazy;
     36         tree[root<<1|1].lazy=tree[root].lazy;
     37         tree[root].lazy=0;
     38     }
     39 }
     40 void build_tree(int root,int l,int r)
     41 {
     42     if(l==r)
     43     {
     44         tree[root].l=l;
     45         tree[root].r=r;
     46         tree[root].v=1;
     47         tree[root].lazy=1;
     48         return ;
     49     }
     50     tree[root].l=l;
     51     tree[root].r=r;
     52     int mid=(l+r)/2;
     53     build_tree(root<<1,l,mid);
     54     build_tree(root<<1|1,mid+1,r);
     55     push_up(root);
     56 }
     57 void update(int root,int l,int r,int left,int right,int va)
     58 {
     59     if(left<=l && right>=r)
     60     {
     61         tree[root].v=(1<<(va-1));
     62         tree[root].lazy=(1<<(va-1));
     63         return ;
     64     }
     65     int mid=(l+r)/2;
     66     push_down(root);
     67     if(left<=mid)
     68         update(root<<1,l,mid,left,right,va);
     69     if(mid<right)
     70         update(root<<1|1,mid+1,r,left,right,va);
     71     push_up(root);
     72 }
     73 int query(int root,int l,int r,int left,int right)
     74 {
     75     if(left<=l && right>=r)
     76     {
     77         return tree[root].v;
     78     }
     79     int mid=(l+r)/2;
     80     push_down(root);
     81     int ans=0;
     82     if(left<=mid)
     83         ans|=query(root<<1,l,mid,left,right);
     84     if(mid<right)
     85         ans|=query(root<<1|1,mid+1,r,left,right);
     86     return ans;
     87 }
     88 int main()
     89 {
     90     while(scanf("%d %d %d",&n,&t,&q)!=EOF)
     91     {
     92         memset(tree,0,sizeof(tree));
     93         build_tree(1,1,n);
     94         for(int i=1;i<=q;i++)
     95         {
     96             scanf("
    %c",&ch);
     97             if(ch=='C')
     98             {
     99                 scanf("%d %d %d",&x,&y,&z);
    100                 if(x>y)
    101                     swap(x,y);
    102                 update(1,1,n,x,y,z);
    103             }
    104             else
    105             {
    106                 scanf("%d %d",&x,&y);
    107                 if(x>y)
    108                     swap(x,y);
    109                 int ans=query(1,1,n,x,y);
    110                 int cntt=cnt(ans);
    111                 printf("%d
    ",cntt);
    112             }
    113         }
    114     }
    115     return 0;
    116 }

    洛谷2894 hotel 最大子段长

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <iostream>
      4 #include <algorithm>
      5 using namespace std;
      6 struct node
      7 {
      8     int l,r,lazy,lmax,rmax,sum;
      9 }tree[200005];
     10 int n,m,x,y,z;
     11 inline void push_up(int root)
     12 {
     13     if(tree[root<<1].lmax==tree[root<<1].r-tree[root<<1].l+1)
     14         tree[root].lmax=tree[root<<1].lmax+tree[root<<1|1].lmax;
     15     else
     16         tree[root].lmax=tree[root<<1].lmax;
     17     if(tree[root<<1|1].rmax==tree[root<<1|1].r-tree[root<<1|1].l+1)
     18         tree[root].rmax=tree[root<<1|1].rmax+tree[root<<1].rmax;
     19     else
     20         tree[root].rmax=tree[root<<1|1].rmax;
     21     tree[root].sum=max(tree[root<<1].rmax+tree[root<<1|1].lmax,max(tree[root<<1].sum,tree[root<<1|1].sum));
     22 }
     23 inline void build_tree(int root,int l,int r)
     24 {
     25     if(l==r)
     26     {
     27         tree[root].l=l,tree[root].r=r;
     28         tree[root].lazy=0;
     29         tree[root].lmax=tree[root].rmax=tree[root].sum=r-l+1;
     30         return ;
     31     }
     32     tree[root].l=l,tree[root].r=r;  
     33     tree[root].lazy=0;
     34     tree[root].lmax=tree[root].rmax=tree[root].sum=r-l+1;
     35     int mid=(l+r)/2;
     36     build_tree(root<<1,l,mid);
     37     build_tree(root<<1|1,mid+1,r);
     38     push_up(root);
     39 }
     40 inline void push_down(int root)
     41 {
     42     if(tree[root].lazy==1)
     43     {
     44         tree[root<<1].sum=tree[root<<1].lmax=tree[root<<1].rmax=tree[root<<1].r-tree[root<<1].l+1;
     45         tree[root<<1|1].sum=tree[root<<1|1].lmax=tree[root<<1|1].rmax=tree[root<<1|1].r-tree[root<<1|1].l+1;
     46         tree[root<<1].lazy=tree[root<<1|1].lazy=1;
     47     }
     48     if(tree[root].lazy==2)
     49     {
     50         tree[root<<1].sum=tree[root<<1].lmax=tree[root<<1].rmax=0;
     51         tree[root<<1|1].sum=tree[root<<1|1].lmax=tree[root<<1|1].rmax=0;
     52         tree[root<<1].lazy=tree[root<<1|1].lazy=2;
     53     }
     54     tree[root].lazy=0;
     55     return ;
     56 }
     57 inline void update(int root,int l,int r,int left,int right,int flag)
     58 {
     59     if(left<=l && right>=r)
     60     {
     61         if(flag==1)
     62         {
     63             tree[root].lmax=r-l+1;
     64             tree[root].rmax=r-l+1;
     65             tree[root].sum=r-l+1;
     66             tree[root].lazy=1;
     67         }
     68         else
     69         {
     70             tree[root].lmax=0;
     71             tree[root].rmax=0;
     72             tree[root].sum=0;
     73             tree[root].lazy=2;
     74         }
     75         return ;
     76     }
     77     push_down(root);
     78     int mid=(l+r)/2;
     79     if(left<=mid)
     80         update(root<<1,l,mid,left,right,flag);
     81     if(mid<right)
     82         update(root<<1|1,mid+1,r,left,right,flag);
     83     push_up(root);
     84 }
     85 inline int query(int root,int len)
     86 {
     87     push_down(root);
     88     if(tree[root<<1].sum>=len)
     89         return query(root<<1,len);  
     90     if(tree[root<<1].rmax+tree[root<<1|1].lmax>=len)
     91         return tree[root<<1].r-tree[root<<1].rmax+1;
     92     if(tree[root<<1|1].sum>=len)
     93         return query(root<<1|1,len);
     94 }
     95 int main()
     96 {
     97     scanf("%d %d",&n,&m);
     98     build_tree(1,1,n);
     99     for(int i=1;i<=m;i++)
    100     {
    101         scanf("%d %d",&x,&y);
    102         if(x==1)
    103         {
    104             if(tree[1].sum>=y)
    105             {
    106                 int ans=query(1,y);
    107                 printf("%d
    ",ans);
    108                 update(1,1,n,ans,ans+y-1,2);
    109             }
    110             else
    111             {
    112                 printf("0
    ");
    113             }
    114         }
    115         else
    116         {
    117             scanf("%d",&z);
    118             update(1,1,n,y,y+z-1,1);
    119         }
    120     }
    121     return 0;
    122 }
     
    堆(优先队列)
    洛谷 1792种树
    (反悔堆)
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <cmath>
     7 #include <queue>
     8 using namespace std;
     9 const int N=200005;
    10 struct node
    11 {
    12     int id,num;
    13     node(int ii,int nn)
    14     {
    15         id=ii,num=nn;
    16     }
    17     bool operator < (const node & other)const
    18     {
    19         return num<other.num;
    20     }
    21 };
    22 priority_queue <node> q;
    23 int n,m,d[N],pre[N],next[N],visit[N],ans;
    24 int main()
    25 {
    26     scanf("%d %d",&n,&m);
    27     for(int i=1;i<=n;i++)
    28     {
    29         scanf("%d",&d[i]);
    30         q.push(node(i,d[i]));
    31         pre[i]=i-1; 
    32         next[i]=i+1;
    33     }
    34     pre[1]=n;
    35     next[n]=1;
    36     if(2*m>n)
    37     {
    38         printf("Error!
    ");
    39         return 0;
    40     }
    41     else
    42     {
    43         for(int i=1;i<=m;i++)
    44         {
    45             while(visit[q.top().id])
    46                 q.pop();
    47             node temp=q.top();
    48             q.pop();
    49             ans+=temp.num;
    50             d[temp.id]=d[pre[temp.id]]+d[next[temp.id]]-d[temp.id];
    51             visit[pre[temp.id]]=visit[next[temp.id]]=1;
    52             pre[temp.id]=pre[pre[temp.id]];
    53             next[pre[temp.id]]=temp.id;
    54             next[temp.id]=next[next[temp.id]];
    55             pre[next[temp.id]]=temp.id;
    56             q.push(node(temp.id,d[temp.id]));
    57         }
    58         printf("%d
    ",ans);
    59     }
    60     return 0;
    61 }
    noip 2016 蚯蚓
    三个堆的技巧
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <queue>
     4 #include <algorithm>
     5 typedef long long ll;
     6 using namespace std;
     7 const int N=100005;
     8 int d[N],n,m,q,u,v,t,tot;
     9 queue < int > q1;
    10 queue < int > q2;
    11 queue < int > q3;
    12 bool cmp(int a,int b)
    13 {
    14     return a>b;
    15 }
    16 int getmax()
    17 {
    18     int t1=q1.empty()?-999999999:q1.front();
    19     int t2=q2.empty()?-999999999:q2.front();
    20     int t3=q3.empty()?-999999999:q3.front();
    21     int mmax=max(t1,max(t2,t3));
    22     if(mmax==t1)    q1.pop();
    23     else if(mmax==t2)   q2.pop();
    24     else if(mmax==t3)   q3.pop();
    25     return mmax+tot;
    26 }
    27 int main()
    28 {
    29     scanf("%d %d %d %d %d %d",&n,&m,&q,&u,&v,&t);
    30     for(int i=1;i<=n;i++)
    31         scanf("%d",&d[i]);
    32     sort(d+1,d+n+1,cmp);
    33     for(int i=1;i<=n;i++)
    34         q1.push(d[i]);
    35     for(int i=1;i<=m;tot+=q,i++)
    36     {
    37         int mmax=getmax();
    38         int left,right;
    39         left=mmax*1LL*u/v,right=mmax-left;
    40         q2.push(left-tot-q),q3.push(right-tot-q);
    41         if(i%t==0)
    42             printf("%d ",mmax);
    43     }
    44     printf("
    ");
    45     for(int i=1;i<=n+m;i++)
    46     {
    47         if(i%t==0)
    48         {
    49             int mmax=getmax();
    50             printf("%d ",mmax);
    51         }
    52         else
    53             getmax();
    54     }
    55     return 0;
    56 }

    洛谷1631 序列合并

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 #include <queue>
     7 using namespace std;
     8 struct node
     9 {
    10     int a,b,num;
    11     node(int aa,int bb,int nnum)
    12     {
    13         a=aa,b=bb,num=nnum;
    14     }
    15     node(){}
    16     bool operator < (const node & other) const
    17     {
    18         return num>other.num;
    19     }
    20 };
    21 const int N=100005;
    22 int n,a[N],b[N];
    23 priority_queue < node > q;
    24 int main()
    25 {
    26     scanf("%d",&n);
    27     for(int i=1;i<=n;i++)
    28     {
    29         scanf("%d",&a[i]);
    30     }
    31     for(int i=1;i<=n;i++)
    32     {
    33         scanf("%d",&b[i]);
    34         q.push(node(1,i,a[1]+b[i]));
    35     }
    36     for(int i=1;i<=n;i++)
    37     {
    38         node temp=q.top();
    39         q.pop();
    40         printf("%d ",temp.num);
    41         q.push(node(temp.a+1,temp.b,a[temp.a+1]+b[temp.b]));
    42     }
    43     return 0;
    44 }

    放一个题 usaco 工作安排

    放上代码

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <queue>
     5 using namespace std;
     6 const int N=1e5+10;
     7 struct node
     8 {
     9     int v,t;
    10     bool operator < (const node & other) const
    11     {
    12         return t<other.t;
    13     }
    14 }d[N];
    15 priority_queue < int , vector < int > , greater < int > > q;
    16 int n;
    17 int main()
    18 {
    19     scanf("%d",&n);
    20     for(int i=1;i<=n;i++)
    21     {
    22         scanf("%d %d",&d[i].t,&d[i].v);
    23     }
    24     sort(d+1,d+n+1);
    25     for(int i=1;i<=n;i++)
    26     {
    27         if(q.size()<d[i].t)
    28             q.push(d[i].v);
    29         else if(d[i].v>q.top())
    30         {
    31             q.pop();
    32             q.push(d[i].v);
    33         }
    34     }
    35     long long ans=0;
    36     while(!q.empty())
    37     {
    38         ans+=q.top();
    39         q.pop();
    40     }
    41     printf("%lld
    ",ans);
    42 }
     
    单调队列
    单调栈
    rmq
     
     

    图论:技巧:倒着删边
    最短路:dij(记数),spfa,floyd
    最长路:spfa(无正环),floyd,记数:先spfa,再dfs;
    欧拉回路
    差分约束
    二分图(染色,匹配)
    基环树
    拓扑
    强连通

    割点
    *双连通
    分数规划
     
    dij
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <vector>
     4 #include <cmath>
     5 #include <queue>
     6 #include <cstring>
     7 #include <algorithm>
     8 using namespace std;
     9 const int N=100005;
    10 struct no
    11 {
    12     int x,v;
    13     no(int xx,int vv)
    14     {
    15         x=xx,v=vv;
    16     }
    17     no (){}
    18 };
    19 vector < no > g[N];
    20 struct node
    21 {
    22     int x,d;
    23     node(int xx,int dd)
    24     {
    25         x=xx,d=dd;
    26     }
    27     bool operator < (const node &other )const
    28     {
    29         return d>other.d;
    30     }
    31 };
    32 priority_queue < node > q;
    33 int dist[N],visit[N],n,m,s;
    34 void dij(int x)
    35 {
    36     memset(dist,0x3f,sizeof(dist));
    37     memset(visit,0,sizeof(visit));
    38     dist[x]=0;
    39     q.push(node(x,dist[x]));
    40     while(!q.empty())
    41     {
    42         node temp=q.top();
    43         q.pop();
    44         if(visit[temp.x])
    45            continue; 
    46         visit[temp.x]=1;
    47         for(int i=0;i<g[temp.x].size();i++)
    48         {
    49             no t=g[temp.x][i];
    50             if(!visit[t.x] && dist[t.x]>dist[temp.x]+t.v)
    51             {
    52                 dist[t.x]=dist[temp.x]+t.v;
    53                 q.push(node(t.x,dist[t.x]));
    54             }
    55         }
    56     }
    57 }
    58 int main()
    59 {
    60     scanf("%d %d %d",&n,&m,&s);
    61     for(int i=1;i<=m;i++)
    62     {
    63         int x,y,z;
    64         scanf("%d %d %d",&x,&y,&z);
    65         g[x].push_back(no(y,z));
    66         //g[y].push_back(no(x,z));
    67     }
    68     dij(s);
    69     for(int i=1;i<=n;i++)
    70     {
    71         printf("%lld ",dist[i]);
    72     }
    73 }

    spfa

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 using namespace std;
     8 const int N=100005;
     9 struct node 
    10 {
    11     int x,v;
    12     node(int xx,int vv)
    13     {
    14         x=xx,v=vv;
    15     }
    16 };
    17 vector < node > g[N];
    18 queue < int > q;
    19 int n,m,s,dist[N],visit[N];
    20 void spfa(int x)
    21 {
    22     memset(dist,0x3f,sizeof(dist));
    23     memset(visit,0,sizeof(visit));
    24     dist[x]=0;
    25     visit[x]=1;
    26     q.push(x);
    27     while(!q.empty())
    28     {
    29         int temp=q.front();
    30         q.pop();
    31         visit[temp]=0;
    32         for(int i=0;i<g[temp].size();i++)
    33         {
    34             node t=g[temp][i];
    35             if(dist[t.x]>dist[temp]+t.v)
    36             {
    37                 dist[t.x]=dist[temp]+t.v;
    38                 if(!visit[t.x])
    39                 {
    40                     q.push(t.x);
    41                     visit[t.x]=1;
    42                 }
    43             }
    44         }
    45     }
    46 }
    47 int main()
    48 {
    49     scanf("%d %d %d",&n,&m,&s);
    50     for(int i=1;i<=m;i++)
    51     {
    52         int x,y,z;
    53         scanf("%d %d %d",&x,&y,&z);
    54         g[x].push_back(node(y,z));
    55     }
    56     spfa(s);
    57     for(int i=1;i<=n;i++)
    58         printf("%d ",dist[i]);
    59     return 0;
    60 }

    spfa判负环

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #include <cstring>
     8 using namespace std;
     9 const int N=3005;
    10 struct node
    11 {
    12     int x,v;
    13     node(int xx,int vv)
    14     {
    15         x=xx,v=vv;
    16     }
    17 };
    18 int n,m,dist[N],visit[N],c[N],T;
    19 vector < node > g[N];
    20 
    21 void spfa()
    22 {
    23     memset(dist,0x3f,sizeof(dist));
    24     memset(visit,0,sizeof(dist));
    25     memset(c,0,sizeof(c));  
    26     queue < int > q;
    27     dist[1]=0;
    28     visit[1]=1;
    29     q.push(1);
    30     while(!q.empty())
    31     {
    32         int temp=q.front();
    33         q.pop();
    34         visit[temp]=0;
    35         if(c[temp]>=n)
    36         {
    37             printf("YE5
    ");
    38             return ;
    39         }
    40         for(int i=0;i<g[temp].size();i++)
    41         {
    42             node t=g[temp][i];
    43             if(dist[t.x]>dist[temp]+t.v)
    44             {
    45                 dist[t.x]=dist[temp]+t.v;
    46                 if(!visit[t.x])
    47                 {
    48                     q.push(t.x);
    49                     visit[t.x]=1;
    50                     c[t.x]++;
    51                     if(c[t.x]>=n)
    52                     {
    53                         printf("YE5
    ");
    54                         return ;
    55                     }   
    56                 }
    57             }
    58         }
    59     }
    60     printf("N0
    ");
    61     return ;
    62 }
    63 int main()
    64 {
    65     scanf("%d",&T);
    66     while(T--)
    67     {
    68         scanf("%d %d",&n,&m);
    69         for(int i=1;i<=n;i++)
    70             g[i].clear();
    71         for(int i=1;i<=m;i++)
    72         {
    73             int x,y,z;
    74             scanf("%d %d %d",&x,&y,&z);
    75             if(z<0)
    76                 g[x].push_back(node(y,z));
    77             else
    78                 g[x].push_back(node(y,z)),g[y].push_back(node(x,z));
    79         }
    80         spfa();
    81         
    82     }
    83 }

    floyd

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 using namespace std;
     5 const int INF=999999999;
     6 int n,m,ans,g[200][200];
     7 int main()
     8 {
     9     scanf("%d %d",&n,&m);
    10     for(int i=1;i<=n;i++)
    11         for(int j=1;j<=n;j++)
    12             g[i][j]=INF;
    13     for(int i=1;i<=m;i++)
    14     {
    15         int x,y,z;
    16         scanf("%d %d %d",&x,&y,&z);
    17         g[x][y]=g[y][x]=z;
    18     }
    19     for(int k=1;k<=n;k++)//循环的顺序要记牢
    20         for(int i=1;i<=n;i++)
    21             for(int j=1;j<=n;j++)
    22             {
    23                 if(g[i][j]>g[i][k]+g[k][j])
    24                     g[i][j]=g[i][k]+g[k][j];
    25             }
    26     for(int i=2;i<=n;i++)
    27     {
    28         if(g[1][i]==INF)
    29         {
    30             printf("-1
    ");
    31             return 0;
    32         }
    33         else
    34             ans=max(ans,g[1][i]);
    35     }
    36     printf("%d
    ",ans);
    37 }

    欧拉回路

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <stack>
     6 using namespace std;
     7 stack < int > s;
     8 const int N=2000;
     9 int g[N][N],du[N],n,m;
    10 void dfs(int x)
    11 {
    12     for(int i=1;i<=1024;i++)
    13     {
    14         if(g[x][i])
    15         {
    16             g[x][i]--;
    17             g[i][x]--;
    18             dfs(i);
    19         }
    20     }
    21     s.push(x);
    22 }
    23 int main()
    24 {
    25     scanf("%d",&n);
    26     for(int i=1;i<=n;i++)
    27     {
    28         int x,y;
    29         scanf("%d %d",&x,&y);
    30         du[x]++;
    31         du[y]++;
    32         g[x][y]++,g[y][x]++;
    33     }
    34     int ss=-1;
    35     for(int i=1;i<=1024;i++)
    36     {
    37         if(du[i]%2!=0)
    38         {
    39             if(ss==-1)
    40             ss=i;
    41         }
    42     }
    43     if(ss==-1)
    44         ss=1;
    45     dfs(ss);
    46     while(!s.empty())
    47     {
    48         int temp=s.top();
    49         printf("%d
    ",temp);
    50         s.pop();
    51     }
    52 }

    强联通

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <stack>
     7 using namespace std;
     8 const int N=50005;
     9 vector < int > g[N];
    10 stack < int > s;
    11 int dfsn[N],instack[N],low[N],block[N],b[N];
    12 int n,m,cnt,id;
    13 void tarjan(int x)
    14 {
    15     dfsn[x]=low[x]=++cnt;
    16     instack[x]=1;
    17     s.push(x);
    18     for(int i=0;i<g[x].size();i++)
    19     {
    20         int temp=g[x][i];
    21         if(!dfsn[temp])
    22         {
    23             tarjan(temp);
    24             low[x]=min(low[x],low[temp]);
    25         }
    26         if(instack[temp])
    27         {
    28             low[x]=min(low[x],dfsn[temp]);
    29         }
    30     }
    31     if(dfsn[x]==low[x])
    32     {
    33         id++;
    34         while(!s.empty())
    35         {
    36             int temp2=s.top();
    37             s.pop();
    38             instack[temp2]=0;
    39             block[id]++;
    40             b[temp2]=id;
    41             if(x==temp2)
    42                 break;
    43         }
    44     }
    45 }
    46 int main()
    47 {
    48     scanf("%d %d",&n,&m);
    49     for(int i=1;i<=m;i++)
    50     {
    51         int x,y;
    52         scanf("%d %d",&x,&y);
    53         g[x].push_back(y);   
    54     }
    55     for(int i=1;i<=n;i++)
    56     {
    57         if(!dfsn[i])
    58         {
    59             tarjan(i);
    60         }
    61     }
    62     printf("%d
    ",id);
    63 }

    割点

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <stack>
     7 using namespace std;
     8 const int N=50005;
     9 vector < int > g[N];
    10 stack < int > s;
    11 int dfsn[N],instack[N],low[N],block[N],b[N],flag[N];
    12 int n,m,cnt,id,ans;
    13 void tarjan(int x,int fa)
    14 {
    15     dfsn[x]=low[x]=++cnt;
    16     instack[x]=1;
    17     s.push(x);
    18     for(int i=0;i<g[x].size();i++)
    19     {
    20         int temp=g[x][i];
    21         if(temp==fa)
    22             continue;
    23         if(!dfsn[temp])
    24         {
    25             tarjan(temp,x);
    26             low[x]=min(low[x],low[temp]);
    27             if(fa!=-1 && low[temp]>=dfsn[x])
    28             {
    29                 flag[x]=1;
    30             }
    31         }
    32         if(instack[temp])
    33         {
    34             low[x]=min(low[x],dfsn[temp]);
    35         }
    36     }
    37     if(dfsn[x]==low[x])
    38     {
    39         id++;
    40         while(!s.empty())
    41         {
    42             int temp2=s.top();
    43             s.pop();
    44             instack[temp2]=0;
    45             if(x==temp2)
    46                 break;
    47         }
    48     }
    49 }
    50 int main()
    51 {
    52     scanf("%d %d",&n,&m);
    53     for(int i=1;i<=m;i++)
    54     {
    55         int x,y;
    56         scanf("%d %d",&x,&y);
    57         g[x].push_back(y);
    58         g[y].push_back(x);
    59     }
    60     for(int i=1;i<=n;i++)
    61     {
    62         if(!dfsn[i])
    63         {
    64             tarjan(i,-1);
    65         }
    66     }
    67     for(int i=1;i<=n;i++)
    68     {
    69         if(flag[i]==true)
    70             ans++;
    71     }
    72     printf("%d
    ",ans);
    73     for(int i=1;i<=n;i++)
    74         if(flag[i])
    75             printf("%d ",i);
    76     return 0;
    77 }

    二分图

    匈牙利算法

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <vector>
     5 #include <algorithm>
     6 using namespace std;
     7 const int N=1005;
     8 vector < int > g[N];
     9 int n,m,e,match[N],ans,flag[N];
    10 bool dfs(int x)
    11 {
    12     for(int i=0;i<g[x].size();i++)
    13     {
    14         int temp=g[x][i];
    15         if(!flag[temp])
    16         {
    17             flag[temp]=1;
    18             if(!match[temp] || dfs(match[temp]))
    19             {
    20                 match[temp]=x;
    21                 return true;
    22             }
    23         }
    24     }
    25     return false;
    26 }
    27 int main()
    28 {
    29     scanf("%d %d %d",&n,&m,&e);
    30     for(int i=1;i<=e;i++)
    31     {
    32         int x,y;
    33         scanf("%d %d",&x,&y);
    34         if(y>m)
    35             continue;
    36         g[x].push_back(y);
    37     }
    38     for(int i=1;i<=n;i++)
    39     {
    40         memset(flag,0,sizeof(flag));
    41         int cnt=dfs(i);
    42         ans+=cnt;
    43     }
    44     printf("%d
    ",ans);
    45 }
    树:lca,直径,生成树,*树剖; 
     
    lca模板
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <vector>
     5 #include <cstring>
     6 #include <iostream>
     7 using namespace std;
     8 const int N=500005;
     9 vector < int > g[N];
    10 int fa[N][21],deep[N],n,m,root;
    11 void dfs(int x,int f)
    12 {
    13     deep[x]=deep[f]+1;
    14     fa[x][0]=f;
    15     for(int i=1;i<=20;i++)
    16     {
    17         fa[x][i]=fa[fa[x][i-1]][i-1];
    18     }
    19     for(int i=0;i<g[x].size();i++)
    20     {
    21         int temp=g[x][i];
    22         if(temp!=f)
    23         {
    24             dfs(temp,x);
    25         }
    26     }
    27 }
    28 int query(int a,int b)
    29 {
    30     if(deep[a]>deep[b])
    31         swap(a,b);
    32     int depth=deep[b]-deep[a];
    33     for(int i=20;i>=0;i--)
    34     {
    35         if((1<<i)<=depth)
    36         {
    37             b=fa[b][i];
    38             depth-=(1<<i);
    39         }
    40     }
    41     if(b==a)
    42         return b;
    43     for(int i=20;i>=0;i--)
    44     {
    45         if(fa[a][i]!=fa[b][i])
    46         {
    47             a=fa[a][i];
    48             b=fa[b][i];
    49         }
    50     }
    51     return fa[a][0];
    52 }
    53 int main()
    54 {
    55     scanf("%d %d %d",&n,&m,&root);
    56     for(int i=1;i<n;i++)
    57     {
    58         int x,y;
    59         scanf("%d %d",&x,&y);
    60         g[x].push_back(y);
    61         g[y].push_back(x);
    62     }
    63     dfs(root,0);
    64     for(int i=1;i<=m;i++)
    65     {
    66         int x,y;
    67         scanf("%d %d",&x,&y);
    68         printf("%d
    ",query(x,y));
    69     }
    70     return 0;
    71 }

    kruskal

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <cmath>
     8 using namespace std;
     9 const int N=200005;
    10 struct node
    11 {
    12     int x,y,v;
    13 }g[N];
    14 int fa[N],n,m,tot,ans,cnt;
    15 int find(int x)
    16 {
    17     if(fa[x]==x)
    18         return x;
    19     else
    20         return fa[x]=find(fa[x]);
    21 }
    22 void add(int x,int y,int z)
    23 {
    24     g[++tot].x=x;
    25     g[tot].y=y;
    26     g[tot].v=z;
    27 }
    28 bool cmp(node a,node b)
    29 {
    30     return a.v<b.v;
    31 }
    32 void kruskal()
    33 {
    34     sort(g+1,g+m+1,cmp);
    35     for(int i=1;i<=n;i++)
    36         fa[i]=i;
    37     for(int i=1;i<=tot;i++)
    38     {
    39         int x1=find(g[i].x),x2=find(g[i].y);
    40         if(x1!=x2)
    41         {
    42             fa[x1]=x2;
    43             cnt++;
    44             ans+=g[i].v;
    45         }
    46         if(cnt==n-1)
    47             break;
    48     }
    49 }
    50 int main()
    51 {
    52     scanf("%d %d",&n,&m);
    53     for(int i=1;i<=m;i++)
    54     {
    55         int x,y,z;
    56         scanf("%d %d %d",&x,&y,&z);
    57         add(x,y,z);
    58     }
    59     kruskal();
    60     if(cnt!=n-1)
    61         printf("orz
    ");
    62     else
    63         printf("%d
    ",ans);
    64     return 0;
    65 }
    差分:树上差分,异或差分,前缀和,二维;

    离线操作:树状数组,图论;

    dp:背包,状压,方案数(取模,long long),记忆化,前缀和优化,递推,数位dp,期望dp
     
    01背包
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cstring> 
     6 using namespace std;
     7 int n,V,dp[1010],v[1005],w[1005];
     8 int main()
     9 {
    10     scanf("%d %d",&V,&n); 
    11     for(int i=1;i<=n;i++)
    12     {
    13         scanf("%d %d",&w[i],&v[i]);
    14     }
    15     for(int i=1;i<=n;i++)
    16     {
    17         for(int j=V;j>=w[i];j--)
    18         {
    19             dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    20         }
    21     }
    22     printf("%d
    ",dp[V]);
    23 }

    完全背包

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cstring> 
     6 using namespace std;
     7 int n,V,dp[1010],v[1005],w[1005];
     8 int main()
     9 {
    10     scanf("%d %d",&V,&n); 
    11     for(int i=1;i<=n;i++)
    12     {
    13         scanf("%d %d",&w[i],&v[i]);
    14     }
    15     for(int i=1;i<=n;i++)
    16     {
    17         for(int j=w[i];j<=V;j++)
    18         {
    19             dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    20         }
    21     }
    22     printf("%d
    ",dp[V]);
    23 }

    多重背包

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cstring> 
     6 using namespace std;
     7 int n,V,dp[6010],v[6005],w[6005],c[6005];
     8 int main()
     9 {
    10     scanf("%d %d",&n,&V); 
    11     for(int i=1;i<=n;i++)
    12     {
    13         scanf("%d %d %d",&w[i],&v[i],&c[i]);
    14     }
    15     for(int i=1;i<=n;i++)
    16     {
    17         for(int j=V;j>=w[i];j--)
    18         {
    19             for(int k=0;k<=c[i] && j-k*w[i]>=0;k++)
    20             {
    21                 dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);
    22             }
    23         }
    24     }
    25     printf("%d
    ",dp[V]);
    26 }

    混合背包

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cstring> 
     6 using namespace std;
     7 int n,V,dp[10010],v[10005],w[10005],c[10005];
     8 int main()
     9 {
    10     scanf("%d %d",&V,&n); 
    11     for(int i=1;i<=n;i++)
    12     {
    13         scanf("%d %d %d",&w[i],&v[i],&c[i]);
    14     }
    15     for(int i=1;i<=n;i++)
    16     {
    17         if(c[i]==0)
    18         {
    19             for(int j=w[i];j<=V;j++)
    20             {
    21                 dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    22             }
    23         }
    24         else
    25         {
    26             for(int j=V;j>=w[i];j--)
    27             {
    28                 for(int k=0;k<=c[i] && j-k*w[i]>=0;k++)
    29                 {
    30                     dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);
    31                 }
    32             }
    33         }
    34     }
    35     printf("%d
    ",dp[V]);
    36 }

    分组背包

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <vector>
     5 using namespace std;
     6 const int N=500;
     7 vector < int > g[N];
     8 int n,V,t,w[N],v[N],x,dp[N];
     9 int main()
    10 {
    11     scanf("%d %d %d",&V,&n,&t);
    12     for(int i=1;i<=n;i++)
    13     {
    14         scanf("%d %d %d",&w[i],&v[i],&x);
    15         g[x].push_back(i);
    16     }
    17     for(int i=1;i<=t;i++)
    18     {
    19         for(int j=V;j>=0;j--)
    20         {
    21             for(int k=0;k<g[i].size();k++)
    22             {
    23                 int temp=g[i][k];
    24                 if(j-w[temp]>=0)
    25                 {
    26                     dp[j]=max(dp[j],dp[j-w[temp]]+v[temp]);
    27                 }
    28             }
    29         }
    30     }
    31     printf("%d
    ",dp[V]);
    32     return 0;
    33 }

    有依赖性的背包

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <vector>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cstring>
     7 using namespace std;
     8 const int N=60;
     9 struct node
    10 {
    11     int w,v;
    12     node(int ww,int vv)
    13     {
    14         w=ww,v=vv;
    15     }
    16 };
    17 vector <node> g[N],g1[N];
    18 int n,V,v[N],w[N],c[N],dp[200005];
    19 int main()
    20 {
    21     scanf("%d %d",&V,&n);
    22     for(int i=1;i<=n;i++)
    23     {
    24         scanf("%d %d %d",&w[i],&v[i],&c[i]);
    25         v[i]=v[i]*w[i];
    26         if(c[i])
    27             g[c[i]].push_back(node(w[i],v[i]));
    28     }
    29     for(int i=1;i<=n;i++)
    30     {
    31         if(!g[i].empty())
    32         {
    33             memset(dp,0,sizeof(dp));
    34             for(int k=0;k<g[i].size();k++)
    35             {
    36                 for(int j=V-w[i];j>=g[i][k].w;j--)
    37                 {
    38                     dp[j]=max(dp[j],dp[j-g[i][k].w]+g[i][k].v);//01背包
    39                 }
    40             }
    41             for(int j=1;j<=V-w[i];j++)
    42             {
    43                 if(dp[j] && dp[j-1]!=dp[j])
    44                     g1[i].push_back(node(w[i]+j,dp[j]+v[i]));
    45             }
    46             g1[i].push_back(node(w[i],v[i]));
    47         }
    48         else if(!c[i])
    49         {
    50             g1[i].push_back(node(w[i],v[i]));
    51         }
    52     }
    53     memset(dp,0,sizeof(dp));
    54     for(int i=1;i<=n;i++)//分组背包
    55     {
    56         for(int j=V;j>=0;j--)
    57         {
    58             for(int k=0;k<g1[i].size();k++)
    59             {
    60                 if(j>=g1[i][k].w)
    61                     dp[j]=max(dp[j],dp[j-g1[i][k].w]+g1[i][k].v);
    62             }
    63         }
    64     }
    65     printf("%d
    ",dp[V]);
    66     return 0;
    67 }

    有多重限制的背包

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cmath>
     7 using namespace std;
     8 const int N=200;
     9 int n,m,t,tt[N],money[N],dp[500][500];
    10 int main()
    11 {
    12     scanf("%d %d %d",&n,&m,&t);
    13     for(int i=1;i<=n;i++)
    14     {
    15         scanf("%d %d",&tt[i],&money[i]);
    16     }
    17     for(int i=1;i<=n;i++)
    18     {
    19         for(int j=m;j>=money[i];j--)
    20         for(int k=t;k>=tt[i];k--)
    21         {
    22             dp[j][k]=max(dp[j][k],dp[j-money[i]][k-tt[i]]+1);
    23         }
    24     }
    25     printf("%d
    ",dp[m][t]);
    26 }

    贪心 二分
     

    字符串:kmp,hash,trie树,string,manecher;
     
     
    数论:ksm,矩阵乘法,斐波那契,线性筛,欧拉函数,exgcd(同余方程),组合数学,容斥原理,高斯消元,期望,尺取法,gcd,高精度,lcm,逆元
     
    快速幂
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 using namespace std;
     5 typedef long long ll;
     6 ll n,m,k;
     7 ll quick_pow(ll a,ll b)
     8 {
     9     ll ans=1;
    10     while(b)
    11     {
    12         if(b&1)
    13             ans=(ans*a)%k;
    14         a=(a*a)%k;
    15         b>>=1;
    16     }
    17     return ans%k;
    18 }
    19 int main()
    20 {
    21     scanf("%lld %lld %lld",&n,&m,&k);    
    22     ll ans=quick_pow(n,m);
    23     printf("%lld^%lld mod %lld=%lld",n,m,k,ans);
    24 }

    矩阵乘法&&快速幂

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cstring>
     6 using namespace std;
     7 const int mod=1e9+7;
     8 const int N=200;
     9 typedef long long ll;
    10 struct node
    11 {
    12     ll a[N][N];
    13     node(){
    14         memset(a,0,sizeof(a));
    15     }
    16 }d;
    17 ll n,k;
    18 node mul(const node &a,const node &b)
    19 {
    20     node temp;
    21     for(ll i=1;i<=n;i++)
    22         for(ll j=1;j<=n;j++)
    23             for(ll k=1;k<=n;k++)
    24             {
    25                 temp.a[i][j]=(temp.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
    26             }
    27     return temp;
    28 }
    29 node quick_pow(node a,ll b)
    30 {
    31     node ans;
    32     for(ll i=1;i<=n;i++)
    33         ans.a[i][i]=1;
    34     while(b)
    35     {
    36         if(b&1)
    37             ans=mul(ans,a);
    38         a=mul(a,a);
    39         b>>=1;
    40     }
    41     return ans;
    42 }
    43 int main()
    44 {
    45     scanf("%lld %lld",&n,&k);
    46     for(ll i=1;i<=n;i++)
    47         for(ll j=1;j<=n;j++)
    48         {
    49             scanf("%lld",&d.a[i][j]); 
    50         }
    51     node temp=quick_pow(d,k);
    52     for(int i=1;i<=n;i++)
    53     {
    54         for(int j=1;j<=n;j++)
    55         {
    56             printf("%lld ",temp.a[i][j]);
    57         }
    58         printf("
    ");
    59     }
    60         
    61 }

    斐波拉契

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <cstring>
     6 using namespace std;
     7 const int mod=1e9+7;
     8 const int N=200;
     9 typedef long long ll;
    10 ll n;
    11 struct node
    12 {
    13     ll a[3][3];
    14     node(){
    15         memset(a,0,sizeof(a));
    16     }
    17 }d,t;
    18 node mul(node a,node b) 
    19 {
    20     node temp;
    21     for(ll i=1;i<=2;i++)
    22         for(ll j=1;j<=2;j++)
    23             for(ll k=1;k<=2;k++)
    24             {
    25                 temp.a[i][j]=(temp.a[i][j]+(a.a[i][k]*b.a[k][j])%mod)%mod;
    26             }
    27     return temp;
    28 }
    29 node quick_pow(node a,node ans,ll b)
    30 {
    31     while(b)
    32     {
    33         if(b&1)
    34             ans=mul(ans,a);
    35         a=mul(a,a);
    36         b>>=1;
    37     }
    38     return ans;
    39 }
    40 int main()
    41 {
    42     scanf("%lld",&n);
    43     if(n==1)
    44     {
    45         printf("1
    ");
    46         return 0;
    47     }   
    48     if(n==2)
    49     {
    50         printf("1
    ");
    51         return 0;
    52     }
    53     d.a[1][1]=1,d.a[1][2]=1;
    54     d.a[2][1]=1,d.a[2][2]=0;
    55     t.a[1][1]=1,t.a[1][2]=1;
    56     t.a[2][1]=1,t.a[2][2]=0;
    57     t=quick_pow(d,t,n);
    58     printf("%lld
    ",t.a[2][2]);
    59     return 0;
    60 }

    exgcd逆元

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <cmath>
     5 using namespace std;
     6 void exgcd(int a,int b,int &x,int &y)
     7 {
     8     if(b==0)
     9     {
    10         x=1,y=0;
    11         return ;
    12     }
    13     exgcd(b,a%b,x,y);
    14     int temp=x;
    15     x=y;
    16     y=temp-a/b*y;
    17 }
    18 int main()
    19 {
    20     int a,b,x,y;
    21     cin>>a>>b;
    22     exgcd(a,b,x,y);
    23     printf("%d
    ",(x%b+b)%b);
    24     return 0;
    25 }

    gcd

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <cmath>
     5 using namespace std;
     6 int gcd(int a,int b)
     7 {
     8     return b==0?a:gcd(b,a%b);
     9 }
    10 int main()
    11 {
    12     int a,b;
    13     cin>>a>>b;
    14     int ans=gcd(a,b);
    15     printf("%d
    ",ans);
    16     return 0;
    17 }

    组合数

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <iostream>
     4 #include <cmath>
     5 using namespace std;
     6 const int mod=1e9+7;
     7 int c[1000][1000],n;
     8 int main()
     9 {
    10     scanf("%d",&n);
    11     for(int i=0;i<=n;i++)
    12         c[i][0]=1;
    13     for(int i=1;i<=n;i++)
    14         for(int j=1;j<=i;j++)
    15             c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
    16     return 0;
    17 }

    线性筛

    set,map 
     
    分块,莫队,离散
     
  • 相关阅读:
    344. 反转字符串
    942. 增减字符串匹配
    CGO内部机制
    CGO函数调用
    CGO类型转换
    CGO基础
    Go net/http代理
    GO-中间件(Middleware )
    Go如何巧妙使用runtime.SetFinalizer
    ARM基础
  • 原文地址:https://www.cnblogs.com/wzrdl/p/9907202.html
Copyright © 2020-2023  润新知