---转载请征求博主同意
写这个博客目的就是为了记录下学过的模板方便我这焫鷄复习吧//dalao们绕道
近期学的:
(1)来自机房学长jjh大神教的求1~n的所有最小素因数和加上本焫鷄的批注
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath>//求1~n的最小质因数 using namespace std; const int MAXN=1e6+5; const int LIM=1e6; int prime[MAXN],mnp[MAXN],cnt=0; bool vis[MAXN]; int main() { for(int i=2;i<=LIM;i++) { if(!vis[i]) { mnp[i]=i;//最小质因数 prime[++cnt]=i;//质因数 } for(int j=1;j<=cnt;j++) { if(1LL*i*prime[j]>LIM) break; vis[i*prime[j]]=1;//合数直接标记 if(i%prime[j]==0)//如果i可以整除以prime[j] { mnp[i*prime[j]]=mnp[i];//那么这个数的最小质因数就为i的最小质因数 break; } else //否则 mnp[i*prime[j]]=prime[j];//他的最小质因数就为prime[j] } } }
(2)比较简单的筛法求素数
void shai(int x) { memset(f,1,sizeof(f)); for(int i=2;i<=x;i++) { if(f[i]) { for(int j=i+i;j<=x;j+=i) { f[j]=false; } } } for(int i=2;i<=x;i++) if(f[i]) prime[++len]=i; }
(3)反素数
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define LL long long using namespace std; LL yi[15]={2,3,5,7,11,13,17,19,23,29}; LL n; LL big,num; void dfs(LL x,int y,int limit,int z) { if(x>n) return; if(num<y) { big=x; num=y; } if(num==y&&big>x) { big=x; } LL temp=x; for(int i=1;i<=limit;i++) { temp=temp*yi[z]; if(temp>n) return; dfs(temp,y*(i+1),i,z+1); } } int main() { cin>>n; big=0; num=0; dfs(1,1,50,0); cout<<big<<endl; return 0; }
(4)来个图论的基本算法Bellman-ford
bool Bellman-ford(int st) { memset(dis,10,sizeof(dis)); dis[st]=0; bool rel=0; for(int i=1;i<=n;i++) { rel=0; for(int j=1;j<=len;j++) { if(dis[a[j].x]+a[j].v<dis[a[j].y]) { dis[a[j].y]=dis[a[j].x]+a[j].v; rel=1; } } if(!rel) return 0; } for(int i=1;i<=len;i++) { if(dis[a[i].x]+a[i].v<dis[a[i].y]) { return 1; } } return 0; }
(5)SPFA
void SPFA(int s) { memset(dis,10,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[s]=0;vis[s]=1;q[1]=s; head=0;tail=1; while(head<tail) { int tn=q[++head]; vis[tn]=0; int te=lin[tn]; for(int j=te;j;j=a[j].next) { int tmp=a[j].y; if(dis[tn]+a[j].v<dis[tmp]) { dis[tmp]=dis[tn]+a[j].v; if(!vis[tmp]) { q[++tail]=tmp; vis[tmp]=1; } } } } }
(6)dijkstra算法
void dijkstra(int st) { for(int i=1;i<=n;i++) dis[i]=a[st][i]; memset(vis,0,sizeof(vis)); vis[st]=1;dis[st]=0; for(int i=1;i<n;i++) { int minn=9999999; int k=0; for(int j=1;j<=n;j++) { if(!vis[j]&&dis[j]<minn) { minn=dis[j]; k=j; } } if(k==0) return; vis[k]=1; for(int j=1;j<=n;j++) { if((!vis[j])&&(dis[k]+a[k][j]<dis[j])) dis[j]=dis[k]+a[k][j]; } } }
补:堆优化的Dijkstra+邻接表//听说SPFA死了....
1 void dijkstra(int s) 2 { 3 priority_queue<P,vector<P>,greater<P> > q;//小根堆因为你要找最短路,若你要找最长路,那么用大根堆。 4 memset(dis,0,sizeof(dis)); 5 dis[s]=1; 6 memset(vis,0,sizeof(vis)); 7 q.push(make_pair(dis[s],s)); 8 while(!q.empty()) 9 { 10 P tmp=q.top(); 11 q.pop(); 12 int x=tmp.second; 13 if(vis[x]) continue; 14 vis[x]=true; 15 for(int i=lin[x],y;i;i=a[i].next) 16 { 17 y=a[i].y; 18 if(dis[y]<dis[x]*a[i].v) 19 { 20 dis[y]=dis[x]*a[i].v; 21 if(!vis[y]) 22 q.push(make_pair(dis[y],y));//或者将dis[y]改为-dis[y],这样也就是最长路了 23 } 24 } 25 } 26 }
(7)最小生成树---Prim算法
void Prim(int s) { memset(dis,10,sizeof(dis)); for(int i=1;i<=n;i++) dis[i]=a[s][i];//所有点都不在队列里,除了s memset(vis,0,sizeof(vis)); vis[s]=1; sumn=0; for(int i=2;i<=n;i++) { //寻找现在能到达的边中最短的那条 int minn=a[0][0],c=0; for(int j=1;j<=n;j++) { if((!vis[j])&&(dis[j]<minn)) { minn=dis[j]; c=j; } } //c点到达了,最小生成树长度增加 vis[c]=1; sumn+=minn; //基于这个点做松弛操作 for(int j=1;j<=n;j++) { if((a[c][j]<dis[j])&&(!vis[j])) dis[j]=a[c][j]; } } }
//未完待续(欲知后事如何请听下回分解)
第二回更
(8)先来个网络流(带上Dinic优化)
void insert(int x,int y,int v) { a[++len].y=y; a[len].v=v; a[len].next=lin[x]; lin[x]=len; rev[len]=len+1; a[++len].y=x; a[len].v=0; a[len].next=lin[y]; lin[y]=len; rev[len]=len-1; } int head,tail; bool make_level() { head=0,tail=1; memset(l,-1,sizeof(l)); q[1]=0;l[0]=0; while(head++<tail) { int tn=q[head]; for(int i=lin[tn];i;i=a[i].next) { if(a[i].v&&l[a[i].y]<0) { q[++tail]=a[i].y; l[a[i].y]=l[tn]+1; } } } return l[n]>=0; } long long MAX(long long k,long long flow) { if(k==n) return flow; long long maxflow=0,d=0; for(int i=lin[k];i&&maxflow<flow;i=a[i].next) { if(l[a[i].y]==l[k]+1&&a[i].v) { if(d=MAX(a[i].y,min(flow-maxflow,a[i].v))) { maxflow+=d; a[i].v-=d; a[rev[i]].v+=d; } } } if(!maxflow) l[k]=-1; return maxflow; } void Dinic() { long long d; while(make_level()) while(d=MAX(1,INF)) sum+=d; }
(9)最小生成树---Kruskal算法(中间有并查集的算法详细见(10))
void Kruskal() { for(intt i=1;i<=n;i++) father[i]=i; sort(a+1,a+m+1,mycmp); int cal=0; for(int i=1;i<=len;i++) { int v=getfather(a[i].x); int u=getfather(a[i].y); if(v!=u) { father[v]=u; if(++cal==n-1) { cout<<a[i].v<<endl; return; } } } }
(10)并查集
int getfather(int k)//找到祖先 { if(father[k]==k) return k; father[k]=getfather(father[k]); return father[k]; } void merge(int x,int y)//合并 { int fx=getfather(x); int fy=getfather(y); father[fx]=fy; } bool judge(int x,int y)//判断是否在一个并查集中 { int fx=getfather(x); int fy=getfather(y); return (fx==fy); }
(11)拓扑排序---topsort
void topsort() { int head=0,tail=0; for(int i=1;i<=n;i++) if(!id[i]) q[++tail]=i; while(head<tail) { head++; for(int i=1;i<=n;i++) { if(a[q[head]][i]) { id[i]--; if(!id[i]) q[++tail]=i; } } } }
(补充)topsort(邻接表)
void topsort() { sum[s]=1; int head=0,tail=0; for(int i=1;i<=n;i++) if(!id[i]) q[++tail]=i; while(head<tail) { head++; int tn=q[head]; for(int i=lin[tn];i;i=a[i].next) { int tmp=a[i].y; id[tmp]--; if(!id[tmp]) q[++tail]=tmp; } } }
第三回更
今天就更新一下字符串的东西吧
(12)字符串-----KMP
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define MAXN 1000010 using namespace std; int p[MAXN]; int main() { string a,b; cin>>a>>b; int j=-1; int la=a.size(),lb=b.size(); p[0]=-1; for(int i=1;i<lb;i++) { while((j>=0)&&b[i]!=b[j+1]) j=p[j]; if(b[j+1]==b[i]) j++; p[i]=j; } j=-1; for(int i=0;i<la;i++) { while((j>-1)&&b[j+1]!=a[i]) j=p[j]; if(b[j+1]==a[i]) j++; if(j==lb-1) { cout<<i-j+1<<endl;//b在a中出现的位置 j=p[j]; } } return 0; }
(13)字符串-----trie树
struct node { char ch; //本节点的值 bool endflag; //是否是某个单词的最后一个字符 int link[26]; //26个分叉 } tree[600100]; void add(int k,int node) //k是s的第k个字符,node为当前节点。 { int chindex=s[k]-‘A’; //字符的编号 if (tree[node].link[chindex]==0) //新开节点 { tree[node].link[chindex]=++len; tree[len].ch=s[k]; tree[len].endflag=false; } int nexnode=tree[node].link[chindex]; //下一个节点的下标 if (k==(int)s.size()-1) { tree[nexnode].endflag=true; return; } add(k+1,nexnode); } bool find(int k, int last,int node) //k是要查找字符串s的第k个元素 { int chindex=s[k]-'a'; if (tree[node].link[chindex]==0) return false; int nextnode=tree[node].link[chindex]; if (k==(s.size()-1)) //如果k是最后一个字符 if (tree[nextnode].endflag) return true; else return false; return find(k+1,last,nextnode); }
(14)字符串------AC自动机
struct node//注:fromjzyz ftp: { int endflag; //是否是某个单词的最后一个字符.小心有多个重复的单词 int fail; //失败指针 int link[26]; //26个分叉 } tree[510100]; char s[1001000]; //用字符数组代替字符串,在1000000 个字符条件下,速度会快一些。 //string s; int n,m,len=0,ans,slen; int head,tail,root=0; int q[510000]; void add(int k,int node) //k是s的第k个字符,root为当前节点。 { int chindex=s[k]-'a'; if (tree[node].link[chindex]==0) //新开节点 { tree[node].link[chindex]=++len; tree[len].endflag=0; //因为存在有多个相同的单词 tree[len].fail=root; } int nexnode=tree[node].link[chindex]; if (k==slen-1) //恰好是一个单词的结尾。 { tree[nexnode].endflag++; return; } add(k+1,nexnode); } void init() { scanf("%d ",&n); memset(tree,0,sizeof(tree)); for (int i=0;i<n;i++) { scanf("%s",s); slen=strlen(s); //因为字符串比较多,用了c语言的字符串读入。 add(0,root); } } void buildac()//生成fail指针,建好AC自动机 //用bfs生成一个层次序列,fail指针肯定往前跳。按层次依次求出fail指针 { head=tail=0; q[tail]=root; while (head<=tail) //bfs广度优先遍历 trie树 { //if (head>300000) head=0; int now=q[head++];// 当前的节点 int temp; //用来存储临时的fail指针,是tree的下标 for (int i=0;i<26;i++) // if (tree[now].link[i]) //求link[i].fail指针 { int nextnode=tree[now].link[i]; if (now!=root)//如果是根,那么fail肯定是root { temp=tree[now].fail; while (!tree[temp].link[i] && temp)//找不到与 link[i]匹配的前缀 且没有退到根 temp=tree[temp].fail; //继续向上退 tree[nextnode].fail=tree[temp].link[i]; } q[++tail]=nextnode; //让这个子节点进队。 } } } void find() { ans=0; int now=root; scanf("%s",s); len=strlen(s); //这里用的也是c语言的字符。 for(int i=0;i<len;i++) { int chindex=s[i]-'a'; while( !tree[now].link[chindex] && now!=root)//如果找不到,往回返 now=tree[now].fail; now=tree[now].link[chindex];//下一层传递。 int temp=now;//如果找到某个单词 while(temp!=root&& tree[temp].endflag>-1 ) //如果找到某个单词,累加到结果 { ans+= tree[temp].endflag; tree[temp].endflag=-1; temp=tree[temp].fail; } } printf("%d",ans); } int main() { freopen("ac.in","r",stdin); freopen("ac.out","w",stdout); //scanf("%d",&m); //while (m--) { init(); buildac(); find(); } fclose(stdin);fclose(stdout); return 0; }
第四回更
(15)hash表
const int maxprime=2323237; const int step=7; struct shaodw { int v,num; }hash[maxprime+5]; int n,x; int find(int x) { int temp=x%maxprime; while(hash[temp].v!=0&&hash[temp].v!=x) { temp+=step; if(temp>=maxprime) temp-=maxprime; } return temp; } void insert(int x) { int now=find(x); if(hash[now].v==x) hash[now].num++; else { hash[now].v=x; hash[now].num=1; } } int main() { memset(hash,0,sizeof(hash)); int n; cin>>n; for(int i=1;i<=n;i++) { cin>>x; insert(x); } return 0; }
(16)hash--字符串
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; const unsigned int seed=131; #define mod 2323237 int n,len=0,lin[300n0010]; char c[210]; struct node{ int ne; char ch[210]; }hash[50010]; unsigned int getkey(){ int len=strlen(c); unsigned int key=0; for (int i=0;i<len;i++) key=key*seed+c[i]; return (key&0x7fffffff)%mod; } void add(int key) {hash[++len].ne=lin[key];lin[key]=len;strcpy(hash[len].ch,c);} bool find(){ int key=getkey(); for (int i=lin[key];i;i=hash[i].ne) if (strcmp(hash[i].ch,c)==0) return false; add(key); return true; } int main(){ //freopen("add.in ","r",stdin); scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%s",c); if (!find()) printf("%d ",i); } return 0; }
(17)莫队模板//例题:小Z的袜子
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; inline long long read() { long long x=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } long long gcd(long long a,long long b) {return b==0?a:gcd(b,a%b);} struct shadow { long long l,r,id; }a[300000],S[300000]; long long s[300000],cnt[300000]; long long d[300000],mo[300000]; bool mycmp(shadow x,shadow y) { if(x.l!=y.l) return x.l<y.l; return x.r<y.r; } bool cmp(shadow x,shadow y) {return x.r>y.r;} bool dmp(shadow x,shadow y) {return x.id<y.id;} long long ans=0; int len=0; void simp(long long a,long long b,long long id) { long long t=gcd(a,b); a/=t;b/=t; S[++len].l=a; S[len].r=b; S[len].id=id; } long long str(long long x) {return x*x;} int main() { //freopen("hose.in","r",stdin); //freopen("hose.out","w",stdout); long long n,m; n=read();m=read(); for(int i=1;i<=n;i++) { s[i]=read(); } for(int i=1;i<=m;i++) { a[i].l=read(); a[i].r=read(); a[i].id=i; } sort(a+1,a+1+m,mycmp); int qw=int(sqrt(1.0*m)); int ii; for(ii=qw;ii<=m;ii+=qw) { sort(a+ii-qw+1,a+1+ii,cmp); } if(ii!=m) sort(a+ii+1,a+ii+m+1,cmp); long long l=1; long long r=0; for(int i=1;i<=m;i++) { while(r<a[i].r) { r++; ans-=str(cnt[s[r]]); cnt[s[r]]++; ans+=str(cnt[s[r]]); } while(r>a[i].r) { ans-=str(cnt[s[r]]); cnt[s[r]]--; ans+=str(cnt[s[r]]); r--; } while(l>a[i].l) { l--; ans-=str(cnt[s[l]]); cnt[s[l]]++; ans+=str(cnt[s[l]]); } while(l<a[i].l) { ans-=str(cnt[s[l]]); cnt[s[l]]--; ans+=str(cnt[s[l]]); l++; } long long M=(long long)ans-(a[i].r-a[i].l+1); long long N=(long long)(a[i].r-a[i].l+1)*(a[i].r-a[i].l); simp(M,N,a[i].id); } sort(S+1,S+1+m,dmp); for(int i=1;i<=m;i++) { cout<<S[i].l<<'/'<<S[i].r<<endl; } return 0; }
(18)LCA模板
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } const int MAXN=100100; struct shadow { int y,next; }a[MAXN*4]; int lin[MAXN*4]; int len=0; void insert(int x,int y) { a[++len].next=lin[x]; lin[x]=len; a[len].y=y; } int dep[MAXN*4]; int f[MAXN*4],size[MAXN*4],son[MAXN*4],top[MAXN*4]; void dfs1(int x) { dep[x]=dep[f[x]]+1; size[x]=1; for(int i=lin[x];i;i=a[i].next) { if(a[i].y!=f[x]&&!f[a[i].y]) { f[a[i].y]=x; dfs1(a[i].y); size[x]+=size[a[i].y]; if(size[son[x]]<size[a[i].y]) son[x]=a[i].y; } } } void dfs2(int x) { if(x==son[f[x]]) top[x]=top[f[x]]; else top[x]=x; for(int i=lin[x];i;i=a[i].next) if(f[a[i].y]==x) dfs2(a[i].y); } int ask(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) x=f[top[x]]; else y=f[top[y]]; } if(dep[x]<dep[y]) return x; else return y; } int main() { int n,m; n=read();m=read(); for(int i=1;i<n;i++) { int x,y; x=read();y=read(); insert(x,y); insert(y,x); } dfs1(1); dfs2(1); for(int i=1;i<=m;i++) { int x,y; x=read();y=read(); int ans=ask(x,y); cout<<ans<<endl; } return 0; }
(19)归并排序
int a[100002],c[100002]; void worksort(int l,int r) { int cnt=0;//逆序对个数 int mid,tmp,i,j; if(r>l+1) { mid=(l+r)/2; worksort(l,mid-1); worksort(mid,r); tmp=1; for(i=l,j=mid;i<=mid-1&&j<=r;) { if(a[i]>a[j]) { c[tmp++]=a[j]; cnt+=mid-i; } else c[tmp++]=a[i++]; } if(j<=r) for(;j<=r;j++) c[tmp++]=a[j]; else for(;i<=mid-1;i++) c[tmp++]=a[i]; for(i=l;i<=r;i++) a[i]=c[i]; } else { if(l+1==r) if(a[l]>a[r]) { swap(a[l],a[r]); cnt++; } } }
第五会更
(20)trajan
void trajan(int x) { low[x]=dfn[x]=++num; s.push(x); for(int i=lin[x];i;i=a[i].next) { int g=a[i].y; if(!dfn[g]) { trajan(g); low[x]=min(low[x],low[g]); } else if(!vis[g]) low[x]=min(low[x],dfn[g]); } if(low[x]==dfn[x]) { sum++; while(1) { int t=s.top(); s.pop(); vis[t]=sum; if(t==x) break; } } }
(21)今天学到了一个新东西..因为我们oj限制栈的大小,所以得用一个东西把限制的大小调大(NOIP和CCF这些正规的比赛都不会限制大小但....省选会)
int __size__ = 20 << 20; // 20MB char *__p__ = (char*)malloc(__size__) + __size__; __asm__("movl %0, %%esp " :: "r"(__p__));
(22)Kosaraju算法
void DFS_T(int u) { int i,v; if(used[u])return ; used[u]=1;id[u]=scc; for(i=q[u];i!=-1;i=Tedge[i].pre) { v=Tedge[i].d; if(!used[v]) DFS_T(v); } } void DFS(int v){ int i,u; if(used[v])return ; used[v]=1; for(i=p[v];i!=-1;i=edge[i].pre) { u=edge[i].d; if(!used[u])DFS(u); } order[++num]=v; } int Kosaraju() { int i,j,k,v,u; memset(used,0,sizeof(used));num=0; for(i=1;i<=n;++i) if(!used[i]) DFS(i); memset(used,0,sizeof(used)); memset(id,0,sizeof(id));scc=0; for(i=num;i>=1;--i) if(!used[order[i]]) scc++,DFS_T(order[i]); }
第六会更
(23)费用流模板
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstdlib> #include<cstring> #include<string> #include<iomanip> using namespace std; const int maxn=10100; const int oo=202116108; //memset 12 的值 struct node { int y,v,flow,next; //v是费用,flow是流量 int reverse; //反向变的编号。 }edge[5*maxn]; // 邻接表的 边数组 int link[maxn]; //邻接表的 点数组 int q[1000010]; int dis[maxn],tot=0; int temp,ans=0; int n,m,s,t; //s是源点, t是汇点。 bool vis[maxn]; int lastnode[maxn],lastedge[maxn]; //记录增广路径用。 void add (int x,int y,int z,int c,int re) { edge[++tot].y=y; edge[tot].v=-z; edge[tot].flow=c; edge[tot].reverse=tot+re; edge[tot].next=link[x]; link[x]=tot; } void init() { scanf("%d %d", &n,&m); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { int xx=(i-1)*m+j; //二维压一维。xx表示第i行第j列点的编号 int yy=2*xx; xx=yy-1; scanf("%d" ,&temp); add(xx,yy,temp,1,1); //正向边 add(yy,xx,-temp,0,-1); //反向边,退流的话把相关的费用返还。 if (j<m) //当前点右方有点 { add(yy,yy+1,0,1,1); //右方连一个费用为0,流量为1的边。 add(yy+1,yy,0,0,-1); //逆向边的流量初值为0; } if (i<n) { add(yy,yy+2*m-1,0,1,1); //下方的边费用也是1. add(yy+2*m-1,yy,0,0,-1); } s=1; t=n*m*2-1; edge[s].flow=2; //源点出去的流量只为2.限制了总体流量。 } } bool spfa() { memset(vis,0,sizeof(vis)); memset(dis,12,sizeof(dis)); dis[1]=0; vis[1]=true; q[0]=1; int head=0,tail=0; while (head<=tail) //队列不为空 { int tn=q[head++]; for (int te=link[tn];te;te=edge[te].next) //枚举边 { int ty=edge[te].y; if (edge[te].flow &&(dis[tn]+edge[te].v<dis[ty])) //首先的有流量再判断费用 { if (!vis[ty]) //不在队列里。 { q[++tail]=ty; vis[ty]=true; } dis[ty]=dis[tn]+edge[te].v; lastnode[ty]=tn; lastedge[ty]=te; //增广路的记录,用于下面的增广。 } } vis[tn]=false; } return(dis[t]!=oo); //如果到t的最短距离存在,表明存在一个费用最小的增广路。 } void agu() //按照增广路径进行流量增减 { int delta=oo; for (int now=t;now!=s;now=lastnode[now]) if (edge[lastedge[now]].flow<delta ) //找出流量 delta=edge[lastedge[now]].flow; for (int now=t;now!=s;now=lastnode[now]) //更新流量 { int te=lastedge[now]; edge[te].flow-=delta; int re=edge[te].reverse; edge[re].flow+=delta; ans+=delta*(-edge[te].v); } } void costflow() { while (spfa()) agu(); cout<<ans<<endl; } int main() { freopen("message.in","r",stdin); freopen("message.out","w",stdout); init(); costflow(); fclose(stdin);fclose(stdout); return 0; }
(24)输出n位小数
cout<<setiosflags(ios::fixed)<<setprecision(n);//n为你要输出小数的位数记得加上头文件#include<iomanip>
(25)二分图------邻接矩阵(DFS)
bool find(int x) { for(int i=1;i<=m;i++) { if(a[x][i]&&!vis[i]) { vis[i]=1; if(!id[i]||find(id[i])) { id[i]=x; return true; } } } return false; } int main() { for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); bool flag=find(i); if(flag) { ans++; } } cout<<ans<<endl; return 0; }
//vector的一些用法
push_back 在数组的最后添加一个数据 pop_back 去掉数组的最后一个数据 at 得到编号位置的数据 size 当前使用数据的大小 erase 删除指针指向的数据项 clear 清空当前的vector empty 判断vector是否为空 swap 与另一个vector交换数据 begin 返回第一个元素 end 返回最后一个元素 //头文件 #include<vector>
//位运算一些基本技巧
1 x&y 表示在x和y的二进制中如果同位上x和y的数都为一则为一否则为0;如下 2 10010110 3 & 01011010 4 ------------------------- 5 00010010 6 x|y 表示在x和y的二进制中如果同为上的x和y的数有一个为一的话那么就为一否则为0,如下: 7 1011011 8 | 0110001 9 ------------------------ 10 1111011 11 x^y(异或) 表示x和y的二进制中如果同位上一个为1,一个为0那么为1,都为1或都为0则为0 如下: 12 1100101 13 ^ 0111011 14 ------------------------- 15 1011110 16 ~x 则表示把x二进制中所有为0变1,1变0,取反的时候是无符号的
(27)dfs序递归版
void dfs(int now,int father) { l[now]=++cnt; for(int i=linkk[now];i;i=e[i].next) { int tn=e[i].y; if(tn==father) continue; dfs(tn,now); } r[now]=cnt; }
(28)dfs序非递归版
void Shadow() { memset(id,0,sizeof(id)); memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); for(int i=1;i<=n;i++) id[i]=linkk[i]; stack[++top]=1,stack[0]=0; while(top) { int now=stack[top]; if(!l[now]) l[now]=++cnt,dep[now]=dep[stack[top-1]]+1,v[now]=v[stack[top-1]]+v[now]; if(id[now]) { int edgee=id[now]; id[now]=e[edgee].next; if(e[edgee].y==stack[top-1]) continue; stack[++top]=e[edgee].y; } else r[stack[top--]]=cnt; } }
(29)树链剖分+线段树(ojP2047,soj375)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define MAXN 101000 using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct shadow { int y,next; }a[MAXN*2]; int d[MAXN][3]; int n,len=0,lin[MAXN*2]; void insert(int x,int y) { a[++len].y=y; a[len].next=lin[x]; lin[x]=len; } int siz[MAXN],top[MAXN],fa[MAXN],w[MAXN]; int son[MAXN],tree[MAXN],dep[MAXN],num=0; void dfs(int x) { siz[x]=1;son[x]=0; for(int i=lin[x];i;i=a[i].next) { int tmp=a[i].y; if(tmp!=fa[x]) { fa[tmp]=x; dep[tmp]=dep[x]+1; dfs(tmp); if(siz[tmp]>siz[son[x]]) son[x]=tmp; siz[x]+=siz[tmp]; } } } void build(int x,int y) { w[x]=++num; top[x]=y; if(son[x]) build(son[x],top[x]); for(int i=lin[x];i;i=a[i].next) { int tmp=a[i].y; if(tmp!=son[x] &&tmp!=fa[x]) build(tmp,tmp); } } void updata(int root,int lo,int hi,int g,int x) { if(g>hi||lo>g) return; if(lo==hi) { tree[root]=x; return ; } int mid=(hi+lo)/2,ls=root<<1,rs=root<<1|1; updata(ls,lo,mid,g,x); updata(rs,mid+1,hi,g,x); tree[root]=max(tree[ls],tree[rs]); } int search(int root,int lo,int hi,int l,int r) { if(l>hi||r<lo) return 0; if(l<=lo&&hi<=r) return tree[root]; int mid=(lo+hi)/2,ls=root<<1,rs=root<<1|1; int templ=search(ls,lo,mid,l,r); int tempr=search(rs,mid+1,hi,l,r); return max(templ,tempr); } inline int find(int x,int y) { int f1=top[x],f2=top[y],tmp=0; while(f1!=f2) { if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); tmp=max(tmp,search(1,1,num,w[f1],w[x])); x=fa[f1];f1=top[x]; } if(x==y) return tmp; if(dep[x]>dep[y]) swap(x,y); return max(tmp,search(1,1,num,w[son[x]],w[y])); } char ch[MAXN]; inline void r() { ch[0]=' '; while(ch[0]<'C'||ch[0]>'Q') scanf("%s",ch); } int main() { int __size__ = 20 << 20; // 20MB char *__p__ = (char*)malloc(__size__) + __size__; __asm__("movl %0, %%esp " :: "r"(__p__)); int t=read(); for(int i=1;i<=t;i++) { memset(siz,0,sizeof(siz)); memset(lin,0,sizeof(lin)); memset(tree,0,sizeof(tree)); n=read(); int oo=(n+1)/2; for(int j=1;j<n;j++) { int x=read(),y=read(),z=read(); d[j][0]=x;d[j][1]=y;d[j][2]=z; insert(x,y);insert(y,x); } dfs(oo); build(oo,oo); for(int i=1;i<n;i++) { if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]); updata(1,1,num,w[d[i][1]],d[i][2]); } for(r();ch[0]!='D';r()) { int q=read(),h=read(); if(ch[0]=='Q') cout<<find(q,h)<<endl; else updata(1,1,num,w[d[q][1]],h); } } return 0; }
//连个stl全排序的函数
next_permutation(a+1,a+1+n);//排1,2,3,4....n prev_permutation(a+1,a+1+n);//排n-1,n-2,n-3.....1
(30)next_premutation的代码实现
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int a[100000]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++)//一共调整m次 {//以下为核心代码 int j,k,p,q,temp; j=n-1; while((j>0)&&(a[j]>a[j+1])) j--; if(j>0) { k=n; while(a[k]<a[j]) k--; swap(a[j],a[k]); for(p=j+1,q=n;p<q;p++,q--) swap(a[p],a[q]); } } for(int i=1;i<=n;i++) cout<<a[i]<<' '; cout<<endl; return 0; }
(31)[noip2006普及]Jam的计数法(解此类问题的代码,由上一组合产生下一组合)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; char ch[26]; int main() { int l,r,w; cin>>l>>r>>w; cin>>ch; r=r+'a'-1; for(int i=1;i<=5;i++) { int j=w-1; while((j>=0)&&(ch[j]==r-(w-1-j))) j--; if(j<0) break; ch[j]++; for(int k=j+1;k<w;k++) ch[k]=ch[k-1]+1; for(int j=0;j<=w;j++) cout<<ch[j]; cout<<endl; } return 0; }
//带权中位数,例题:OJ1627
给出了若干个排列在一条直线上的点,每个点有一个权值,比如说货物量、人数什么的,然后让我们找出使所有点的货物、人集合到一个点的总代价最小的位置//带权中位数就是求这个东西的 网上看证明一大堆,大概来说,打个比方,现在有一列的东西,每个东西都有一个权值。 让你在这一列中选一个地方使所有物品到这个位置的距离×权值最小。然后你就可以将这列东西分为两部分,先算出权值和的平均数。 然后一个从前向后记录前缀和,当这个前缀和大于权值平均数时,这样这列物品就被分为了两部分。 左半边的所有权值加上中间这个物品的权值大于右边,右边的总权值加上中间的权值大于左边,那么这个点的权值就是带权中位数//大概就是个这个东西
//oj1627代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct shadow { int x,y,v; }a[101000]; bool mycmp(shadow x,shadow y) {return x.x<y.x;} bool emp(shadow x,shadow y) {return x.y<y.y;} int main() { int n=read(),sum=0; for(int i=1;i<=n;i++) { a[i].x=read();a[i].y=read(); int p=read(),k=read(); a[i].v=p*k; sum+=a[i].v; } sum=(sum+1)/2; sort(a+1,a+1+n,mycmp); int ansx=0,ansy=0,tmp=0; for(int i=1;i<=n;i++) { tmp+=a[i].v; if(tmp>=sum) { ansx=a[i].x; break; } } tmp=0; sort(a+1,a+1+n,emp); for(int i=1;i<=n;i++) { tmp+=a[i].v; if(tmp>=sum) { ansy=a[i].y; break; } } cout<<ansx<<' '<<ansy<<endl; return 0; }
(32)dfs序
void dfs(int p) { f[p]=true; in[p]=++tot; for(int i=lin[p];i;i=e[i].next) { if(!f[e[i].y]) dfs(e[i].y); } out[p]=tot; }
(33)2-sat模板//例题:bzoj1823满汉全席
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define MAXN 3100 using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } int get() { int x; char c=getchar(); while(c!='m'&&c!='h') c=getchar(); if(c=='m') x=read()*2; else x=read()*2-1; return x; } struct shadow { int y,next; }a[MAXN*2]; int lin[MAXN],dfn[MAXN],low[MAXN],q[MAXN],b[MAXN]; int len=0,ind=0,l=0,sum=0; bool vis[MAXN]; void insert(int x,int y) { a[++len].y=y; a[len].next=lin[x]; lin[x]=len; } void trajan(int x) { low[x]=dfn[x]=++ind; vis[x]=1;q[++l]=x; for(int i=lin[x];i;i=a[i].next) if(!dfn[a[i].y]) { trajan(a[i].y); low[x]=min(low[x],low[a[i].y]); } else if(vis[a[i].y]) low[x]=min(low[x],dfn[a[i].y]); if(low[x]==dfn[x]) { sum++; int now=0; while(now!=x) { now=q[l--]; b[now]=sum; vis[now]=0; } } } int main() { int k=read(); for(int i=1;i<=k;i++) { ind=l=sum=len=0; int n=read(),m=read(); memset(lin,0,sizeof(lin)); memset(dfn,0,sizeof(dfn)); int x,y,X,Y; for(int i=1;i<=m;i++) { x=get();y=get(); if(x%2==0) X=x--; else X=x++; if(y%2==0) Y=y--; else Y=y++; insert(X,y); insert(Y,x); } bool f=0; for(int i=1;i<=n*2;i++) if(!dfn[i]) trajan(i); for(int i=1;i<=n;i++) if(b[i*2]==b[i*2-1]) { cout<<"BAD"<<endl; f=1; break; } if(!f) cout<<"GOOD"<<endl; } return 0; }
(34)高斯消元
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; double a[1100][1100]; int n; void Gauss() { int now=1,x,y; double t; for(int i=1;i<=n;i++) { for(x=now;x<=n;x++) if(a[x][i]!=0) break; if(x>n) continue; if(x!=now) for(int j=1;j<=n+1;j++) swap(a[x][j],a[now][j]); t=a[now][i]; for(int j=1;j<=n+1;j++) a[now][j]/=t; for(int j=1;j<=n;j++) if(j!=now) { t=a[j][i]; for(int k=1;k<=n+1;k++) a[j][k]-=t*a[now][k]; } now++; } } int main() { cin>>n; for(int i=1;i<=n;i++) for(int j=1;j<=n+1;j++) cin>>a[i][j]; Gauss(); for(int i=1;i<=n;i++) cout<<(int)round(a[i][n+1])<<endl; return 0; }
(35)矩阵乘法-------斐波那契数列第n项
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<ctime> #define K 10000 #define LL long long using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct Matrix { LL m[2][2]; }; Matrix A= { 1,1, 1,0 }; Matrix B= { 1,0, 0,1 }; Matrix multi(Matrix a,Matrix b) { Matrix c; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { c.m[i][j]=0; for(int k=0;k<2;k++) c.m[i][j]+=a.m[i][k]*b.m[k][j]%K; c.m[i][j]%=K; } } return c; } Matrix power(Matrix A,int k) { Matrix ans=B,p=A; while(k) { if(k&1) { ans=multi(ans,p); k--; } k>>=1; p=multi(p,p); } return ans; } int main() { for(;;) { LL k; k=read(); if(k==-1) break; if(k==0) { cout<<0<<endl; continue; } Matrix ans=power(A,k-1); cout<<ans.m[0][0]<<endl; } return 0; }
(36)莫比乌斯函数
void mobius() { memset(vis,0,sizeof(vis)); mu[1]=1; for(int i=2;i<=N;i++) { if(!vis[i]) { mu[i]=-1; prime[++l]=i; } for(int j=1;j<=N;j++) { if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } }
(37)中国剩余定理//互质版
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; long long n,x,y,M=1; void exgcd(long long a,long long b,long long &x,long long &y) { if(b==0) { x=1; y=0; return; } exgcd(b,a%b,x,y); int t=x; x=y; y=t-a/b*y; } long long a[1100],b[1100]; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]>>b[i]; M*=a[i]; } long long ans=0; for(int i=1;i<=n;i++) { long long x,y,Mi=M/a[i]; exgcd(Mi,a[i],x,y); ans=((ans+Mi*x*b[i])%M+M)%M; } cout<<ans<<endl; return 0; }
(38)中国剩余定理//非互质版
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define ll long long #define MAXN 101000 using namespace std; inline ll read() { ll x=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } ll m[MAXN],q[MAXN]; void exgcd(ll a,ll b,ll &d,ll &x,ll &y) { if(b==0) { d=a; x=1; y=0; return ; } exgcd(b,a%b,d,x,y); int t=x; x=y; y=t-a/b*y; } ll M; int k; ll China() { ll A=q[1],x,y; M=m[1]; for(int i=2;i<=k;i++) { ll da=q[i]-A,d; exgcd(M,m[i],d,x,y); if(da%d) return -1; ll t=m[i]/d; x*=da/d; x=(x%t+t)%t; A+=x*M; M=M*m[i]/d; A=(A+M)%M; } return A; } int main() { while(~scanf("%d",&k)) { for(int i=1;i<=k;i++) m[i]=read(),q[i]=read(); cout<<China()<<endl; } return 0; }
(39)求杨辉三角第n行
1 c[0]=1; 2 for(int i=1;i<=n;i++)//K为摸数,n为第n行 3 { 4 c[i]=(c[i-1]*(n-i+1)/i)%K; 5 c[i]%=K; 6 }
(40)第二类Stirling数模板//ojp1807例题==模板题
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int a[15][15];//当元素超过20的时候记住用long long int main() { int n,r; cin>>n>>r; memset(a,0,sizeof(a)); for(int i=1;i<15;i++) a[i][1]=1; for(int i=2;i<15;i++) { for(int j=1;j<=i;j++) { a[i][j]=a[i-1][j-1]+j*a[i-1][j]; } } long long ans=1; for(int i=1;i<=r;i++) ans*=i; cout<<a[n][r]*ans<<endl; return 0; }
(41)错位排序
for(int i=2;i<=n;i++) { f[i]=f[i-1]+f[i-2]; f[i]=f[i]*(i-1); }
(42)错位排序-----高精度版//例题HAOI2016 T2放棋子
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 struct shadow 8 { 9 int len; 10 int num[1000]; 11 }a[210],c; 12 void mul(int x,int y) 13 { 14 memset(c.num,0,sizeof(c.num)); 15 c.len=0; 16 int len=a[y].len; 17 for(int i=1;i<=len;i++) 18 { 19 c.num[i]+=(a[y].num[i]*x); 20 if(c.num[i]>=10) 21 { 22 c.num[i+1]=c.num[i]/10; 23 c.num[i]%=10; 24 } 25 } 26 len++; 27 while(c.num[len]>0) 28 { 29 c.num[len+1]=c.num[len]/10; 30 c.num[len++]%=10; 31 } 32 c.len=--len; 33 a[y].len=c.len; 34 for(int i=1;i<=a[y].len;i++) 35 a[y].num[i]=c.num[i]; 36 } 37 void add(int x,int y) 38 { 39 memset(c.num,0,sizeof(c)); 40 int len=a[x].len; 41 if(a[y].len>a[x].len) 42 len=a[y].len; 43 for(int i=1;i<=len;i++) 44 { 45 c.num[i]+=a[x].num[i]+a[y].num[i]; 46 if(c.num[i]>=10) 47 { 48 c.num[i+1]++; 49 c.num[i]=c.num[i]-10; 50 } 51 } 52 if(c.num[len+1]>0) 53 len++; 54 c.len=len; 55 a[x+1].len=len; 56 for(int i=1;i<=len;i++) 57 a[x+1].num[i]=c.num[i]; 58 } 59 int main() 60 { 61 int n; 62 cin>>n; 63 a[0].num[1]=1;a[0].len=1; 64 a[1].num[1]=0;a[1].len=0; 65 for(int i=2;i<=n;i++) 66 { 67 add(i-1,i-2); 68 mul(i-1,i); 69 } 70 for(int i=a[n].len;i>=1;i--) 71 cout<<a[n].num[i]; 72 cout<<endl; 73 return 0; 74 }
(43)高精度乘以单精度
1 void mul(int x) 2 { 3 memset(c.num,0,sizeof(c.num)); 4 c.len=0; 5 int len=a.len; 6 for(int i=1;i<=len;i++) 7 { 8 c.num[i]+=(a.num[i]*x); 9 if(c.num[i]>=10) 10 { 11 c.num[i+1]=c.num[i]/10; 12 c.num[i]%=10; 13 } 14 } 15 len++; 16 while(c.num[len]>0) 17 { 18 c.num[len+1]=c.num[len]/10; 19 c.num[len++]%=10; 20 } 21 c.len=--len; 22 }
(44)高精度乘以高精度
1 #include<iostream> 2 #include<cmath> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdio> 7 using namespace std; 8 struct bignum 9 { 10 int len; 11 int num[1000]; 12 }a,b,c; 13 void big(string s,bignum&c) 14 { 15 int h; 16 reverse(s.begin(),s.end()); 17 h=s.size(); 18 for(int i=0;i<h;i++) 19 c.num[i+1]=int(s[i]-'0'); 20 c.len=s.size(); 21 } 22 void init() 23 { 24 string s1,s2; 25 cin>>s1>>s2; 26 big(s1,a); 27 big(s2,b); 28 } 29 30 int main() 31 { 32 init(); 33 int i,j,len=0; 34 memset(c.num,0,sizeof(c.num)); 35 for(i=1;i<=a.len;i++) 36 for(j=1;j<=b.len;j++) 37 { 38 int k=i+j-1; 39 c.num[k]+=a.num[i]*b.num[j]; 40 while(c.num[k]>=10) 41 { 42 c.num[k+1]+=c.num[k]/10; 43 c.num[k]%=10; 44 k++; 45 } 46 if(k>c.len) c.len=k; 47 } 48 while(c.num[c.len]==0&&c.len>1) 49 c.len--; 50 for(int s=c.len;s>0;s--) 51 cout<<c.num[s]; 52 return 0; 53 }
//折叠有点问题就先不折叠了
(45)高精度加法
1 #include<iostream> 2 #include<string> 3 #include <stdarg.h> 4 #include<cmath> 5 #include<algorithm> 6 #include<iomanip> 7 using namespace std; 8 struct bignum 9 { 10 int len; 11 int num[1000]; 12 }a,b,c; 13 void big(string s,bignum&c) 14 { 15 int h; 16 reverse(s.begin(),s.end()); 17 h=s.size(); 18 for(int i=0;i<h;i++) 19 c.num[i+1]=int(s[i]-'0'); 20 c.len=s.size(); 21 } 22 void init() 23 { 24 string s1,s2; 25 cin>>s1>>s2; 26 big(s1,a); 27 big(s2,b); 28 } 29 int main() 30 { 31 init(); 32 int len=b.len; 33 if(a.len>b.len) len=a.len; 34 for(int i=1;i<=len;i++) 35 { 36 c.num[i]+=a.num[i]+b.num[i]; 37 if(c.num[i]>=10) 38 { 39 c.num[i+1]++; 40 c.num[i]=c.num[i]-10; 41 } 42 } 43 if(c.num[len+1]>0)len++; 44 c.len=len; 45 for(int i=c.len;i>0;i--) 46 cout<<c.num[i]; 47 return 0; 48 }
(46)高精度减法
//猴式智减法??
1 #include<iostream> 2 #include<cmath> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdio> 7 using namespace std; 8 struct bignum 9 { 10 int len; 11 int num[1000]; 12 }a,b,c; 13 void big(string s,bignum&c) 14 { 15 int h; 16 reverse(s.begin(),s.end()); 17 h=s.size(); 18 for(int i=0;i<h;i++) 19 c.num[i+1]=int(s[i]-'0'); 20 c.len=s.size(); 21 } 22 void init() 23 { 24 string s1,s2; 25 cin>>s1>>s2; 26 big(s1,a); 27 big(s2,b); 28 } 29 30 int main() 31 { 32 init(); 33 int i,j,len=0; 34 memset(c.num,0,sizeof(c.num)); 35 for(i=1;i<=a.len;i++) 36 for(j=1;j<=b.len;j++) 37 { 38 int k=i+j-1; 39 c.num[k]+=a.num[i]*b.num[j]; 40 while(c.num[k]>=10) 41 { 42 c.num[k+1]+=c.num[k]/10; 43 c.num[k]%=10; 44 k++; 45 } 46 if(k>c.len) c.len=k; 47 } 48 while(c.num[c.len]==0&&c.len>1) 49 c.len--; 50 for(int s=c.len;s>0;s--) 51 cout<<c.num[s]; 52 return 0; 53 }
(47)高精度除法.....留个坑QAQ
(48)线段树----区间查询最大值,区间修改
1 struct shadow 2 { 3 int delta; 4 int maxx; 5 }tree[MAXN*4]; 6 int search(int l,int r,int root) 7 { 8 int mid,templ,tempr; 9 if(y<l||x>r) 10 return -9999999999; 11 if(x<=l&&y>=r) 12 return tree[root].maxx; 13 mid=(l+r)/2; 14 int D=tree[root].delta; 15 tree[root*2].delta+=D; tree[root*2+1].maxx+=D; 16 tree[root*2+1].delta+=D; tree[root*2+1].maxx+=D; 17 tree[root].delta=0; 18 templ=search(l,mid,root*2); 19 tempr=search(mid+1,r,root*2+1); 20 return max(templ,tempr); 21 } 22 void updata(int l,int r,int root) 23 { 24 int mid; 25 if(x>r||y<l) 26 return; 27 if(x<=l&&y>=r) 28 { 29 tree[root].maxx++; 30 tree[root].delta++; 31 return; 32 } 33 mid=(l+r)/2; 34 int D=tree[root].delta;tree[root].delta=0; 35 tree[root*2].delta+=D;tree[root*2].maxx+=D; 36 tree[root*2+1].delta+=D;tree[root*2+1].maxx+=D; 37 updata(l,mid,root*2); 38 updata(mid+1,r,root*2+1); 39 tree[root].maxx=max(tree[root*2].maxx,tree[root*2+1].maxx); 40 }
(49)树状数组求逆序对
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define MAXN 101000 7 using namespace std; 8 int n; 9 int c[MAXN],a[MAXN]; 10 int lowbit(int x) 11 {return x&-x;} 12 void add(int i,int x) 13 { 14 while(i<=MAXN) 15 { 16 c[i]+=x; 17 i+=lowbit(i); 18 } 19 } 20 int sum(int i) 21 { 22 int ans=0; 23 while(i>0) 24 { 25 ans+=c[i]; 26 i-=lowbit(i); 27 } 28 return ans; 29 } 30 int main() 31 { 32 //freopen("shadow.in","r",stdin); 33 //freopen("shadow.out","w",stdout); 34 int n; 35 cin>>n; 36 int ans=0; 37 for(int i=1;i<=n;i++) 38 { 39 int x; 40 cin>>x; 41 ans+=i-sum(x+1)-1; 42 //cout<<i<<"-----"<<sum(x-1)<<endl; 43 add(x+1,1); 44 } 45 cout<<ans<<endl; 46 return 0; 47 }
(50)欧拉函数(O(n))
1 void Euler(int x) 2 { 3 memset(check,0,sizeof(check)); 4 int l=0; 5 for(int i=2;i<=x;i++) 6 { 7 if(!check[i]) 8 { 9 prime[++l]=i; 10 phi[i]=i-1; 11 } 12 for(int j=1;j<=l&&prime[j]*i<=x;j++) 13 { 14 check[i*prime[j]]=1; 15 if(i%prime[j]) 16 phi[i*prime[j]]=phi[i]*(prime[j]-1); 17 else 18 { 19 phi[i*prime[j]]=phi[i]*prime[j]; 20 break; 21 } 22 } 23 } 24 }
(51)多重背包//有n个物品和一个容量为C的背包,第i种物品的重量是w[i],价值是v[i],数量为a[i]。求把那些物品放入背包中价值总和最大
1 void bag() 2 { 3 for(int i=1;i<=n;i++) 4 { 5 if(w[i]*a[i]>C) 6 { 7 for(int c=0;c<=C;c++) 8 if(c>=w[i]) 9 f[c]=max(f[c],f[c-w[i]]+v[i]); 10 } 11 else 12 { 13 int sum=a[i],k=1; 14 while(k<sum) 15 { 16 for(int c=C;c>=k*w[i];c--) 17 f[c]=max(f[c],f[c-k*w[i]]+k*v[i]); 18 sum-=k; 19 k+=k; 20 } 21 for(int c=C;c>=sum*w[i];c--) 22 f[c]=max(f[c],f[c-sum*w[i]]+sum*v[i]); 23 } 24 } 25 }
(52)割点---trajan
1 void trajan(int x)//----割点-----// 2 { 3 low[x]=dfn[x]=++ind; 4 for(int i=lin[x];i;i=a[i].next) 5 { 6 int tmp=a[i].y; 7 if(!dfn[tmp]) 8 { 9 trajan(tmp); 10 if(x==h) 11 son++; 12 else 13 { 14 low[x]=min(low[x],low[tmp]); 15 if(low[tmp]>=dfn[x]&&!c[x]) 16 { 17 ans++; 18 c[x]=1; 19 } 20 } 21 } 22 else 23 low[x]=min(low[x],dfn[tmp]); 24 } 25 return ; 26 } 27 void work() 28 { 29 for(int i=1;i<=n;i++) 30 if(!dfn[i]) 31 { 32 son=0; 33 h=i; 34 trajan(i); 35 if(son>1&&c[i]==false) 36 { 37 c[i]=1; 38 ans++; 39 } 40 } 41 //ans为图中的割点数目,if(c[i])那么i就为一个割点 42 }
(53)割边---trajan
1 void trajan(int x,int p=0)//----割边----// 2 { 3 dfn[x]=low[x]=++ind; 4 for(int i=lin[x];i;i=a[i].next) 5 { 6 int tmp=a[i].y; 7 if(!dfn[tmp]) 8 { 9 trajan(tmp,x); 10 low[x]=min(low[x],dfn[tmp]); 11 if(dfn[x]<low[tmp]) 12 { 13 ans[++l].y=x; 14 ans[l].next=tmp; 15 } 16 } 17 else if(dfn[tmp]<low[x]&&tmp!=p) 18 low[x]=dfn[tmp]; 19 }//ans[]数组中保存的即为割边 20 }
第十一回更
作为退役选手的我又回来更新了....//弱弱的补个坑
(54)线段树----单点修改和区间求值
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define MAXN 110000 7 using namespace std; 8 inline int read() 9 { 10 int x=0,f=1; 11 char ch=getchar(); 12 while(ch>'9'||ch<'0') 13 { 14 if(ch=='-') 15 f=-1; 16 ch=getchar(); 17 } 18 while(ch>='0'&&ch<='9') 19 { 20 x=x*10+ch-'0'; 21 ch=getchar(); 22 } 23 return x*f; 24 } 25 struct drt 26 { 27 int v,delta; 28 }tree[MAXN*4]; 29 int x,y; 30 void updata(int l,int r,int root)//单点修改 31 { 32 int mid; 33 if(x<l||x>r) 34 return ; 35 if(l==r) 36 { 37 tree[root].v=y; 38 tree[root].delta=y; 39 return ; 40 } 41 mid=(l+r)>>1; 42 int d=tree[root].delta; 43 tree[root<<1].delta+=d;tree[root<<1].v+=d; 44 tree[root<<1|1].delta+=d;tree[root<<1|1].v+=d; 45 tree[root].delta=0; 46 updata(l,mid,root<<1); 47 updata(mid+1,r,root<<1|1); 48 tree[root].v=tree[root<<1].v+tree[root<<1|1].v; 49 } 50 int search(int l,int r,int root)//区间[x,y]求值 51 { 52 int mid,tmpl,tmpr; 53 if(x>r||y<l) 54 return 0; 55 if(x<=l&&y>=r) 56 return tree[root].v; 57 mid=(l+r)>>1; 58 int d=tree[root].delta; 59 tree[root<<1].v+=d;tree[root<<1].delta+=d; 60 tree[root<<1|1].v+=d;tree[root<<1|1].delta+=d; 61 tree[root].delta=0; 62 tmpl=search(l,mid,root<<1); 63 tmpr=search(mid+1,r,root<<1|1); 64 return (tmpl+tmpr); 65 } 66 int main() 67 { 68 memset(tree,0,sizeof(0)); 69 int n=read(),w=read(); 70 for(int i=1;i<=w;i++) 71 { 72 char ch; 73 cin>>ch; 74 int xx=read(),yy=read(); 75 if(ch=='x')//单点修改 76 { 77 x=xx;y=yy; 78 updata(1,n,1); 79 } 80 else 81 { 82 x=xx;y=yy; 83 int ans=search(1,n,1);//求值 84 cout<<ans<<endl; 85 } 86 } 87 return 0; 88 }
(55)线段树----区间修改和区间求值
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define MAXN 101000 7 #define ll long long 8 using namespace std; 9 inline ll read() 10 { 11 ll x=0,f=1; 12 char ch=getchar(); 13 while(ch>'9'||ch<'0') 14 { 15 if(ch=='-') 16 f=-1; 17 ch=getchar(); 18 } 19 while(ch>='0'&&ch<='9') 20 { 21 x=x*10+ch-'0'; 22 ch=getchar(); 23 } 24 return x*f; 25 } 26 struct drt 27 { 28 ll v,d; 29 }a[MAXN*4]; 30 ll x,y,k; 31 ll s[MAXN]; 32 void build(ll l,ll r,ll root) 33 { 34 ll mid; 35 if(l==r) 36 { 37 a[root].v=s[l]; 38 return ; 39 } 40 mid=(l+r)>>1; 41 a[root].d=0; 42 build(l,mid,root<<1); 43 build(mid+1,r,root<<1|1); 44 a[root].v=a[root<<1].v+a[root<<1|1].v; 45 } 46 void f(ll root,ll l,ll r,ll k) 47 { 48 a[root].d+=k; 49 a[root].v+=k*(r-l+1); 50 } 51 void updata(ll l,ll r,ll root) 52 { 53 ll mid; 54 if(x>r||y<l) 55 return ; 56 if(x<=l&&y>=r) 57 { 58 a[root].v+=k*(r-l+1); 59 a[root].d+=k; 60 return ; 61 } 62 mid=(l+r)>>1; 63 f(root<<1,l,mid,a[root].d); 64 f(root<<1|1,mid+1,r,a[root].d); 65 a[root].d=0; 66 if(x<=mid) updata(l,mid,root<<1); 67 if(y>mid) updata(mid+1,r,root<<1|1); 68 a[root].v=a[root<<1].v+a[root<<1|1].v; 69 } 70 ll search(ll l,ll r,ll root) 71 { 72 ll mid,sum=0; 73 if(x>r||y<l) 74 return 0; 75 if(x<=l&&y>=r) 76 return a[root].v; 77 mid=(l+r)>>1; 78 int D=a[root].d; 79 f(root<<1,l,mid,D); 80 f(root<<1|1,mid+1,r,D); 81 a[root].d=0; 82 if(x<=mid) sum+=search(l,mid,root<<1); 83 if(y>mid) sum+=search(mid+1,r,root<<1|1); 84 return sum; 85 } 86 int main() 87 { 88 ll n=read(),m=read(); 89 for(int i=1;i<=n;i++) 90 s[i]=read(); 91 build(1,n,1); 92 for(int i=1;i<=m;i++) 93 { 94 ll c=read(); 95 if(c==1) 96 { 97 x=read();y=read(); 98 k=read(); 99 updata(1,n,1); 100 } 101 else 102 { 103 x=read(),y=read(); 104 ll ans=search(1,n,1); 105 cout<<ans<<endl; 106 } 107 } 108 return 0; 109 }