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
单调栈
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
分块,莫队,离散