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\n");
38             }
39             else
40             {
41                 printf("N\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\n",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\n");
78         else if(tot>1)
79             printf("Can not determine\n");
80         else
81             printf("Player %d can be determined to be the judge after %d lines\n",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\n",abs(deep[x]-deep[y])-1);
36     }
37     else
38     {
39         printf("-1\n");
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\n",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\n",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("\n%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\n",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\n",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\n",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\n",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("\n%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\n",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\n",ans);
108                 update(1,1,n,ans,ans+y-1,2);
109             }
110             else
111             {
112                 printf("0\n");
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!\n");
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\n",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("\n");
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\n",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\n");
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\n");
54                         return ;
55                     }   
56                 }
57             }
58         }
59     }
60     printf("N0\n");
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\n");
31             return 0;
32         }
33         else
34             ans=max(ans,g[1][i]);
35     }
36     printf("%d\n",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\n",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\n",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\n",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\n",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\n",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\n");
62     else
63         printf("%d\n",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\n",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\n",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\n",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\n",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\n",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\n",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\n",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("\n");
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\n");
46         return 0;
47     }   
48     if(n==2)
49     {
50         printf("1\n");
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\n",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\n",(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\n",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 
 
分块,莫队,离散
 
posted @ 2018-11-05 16:28  没有名字的大佬  阅读(261)  评论(0编辑  收藏  举报