【Code Library】不超过25个页面的材料
来源:互联网 发布:java高级编程 pdf 编辑:程序博客网 时间:2024/05/16 07:19
---------------
一、模板
---
1、NGUNSTTD-PO
Name: NeverGiveUpNeverSurrenderTerribleTerribleDamage-PowerOverwhelmingUsage: Put it before main function
Tags: 头文件 循环 常用语句
---
/** head-file **/#include <iostream>#include <fstream>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <vector>#include <queue>#include <stack>#include <list>#include <set>#include <map>#include <algorithm>/** define-for **/#define REP(i, n) for (int i=0;i<int(n);++i)#define FOR(i, a, b) for (int i=int(a);i<int(b);++i)#define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)#define REP_1(i, n) for (int i=1;i<=int(n);++i)#define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)#define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)#define REP_N(i, n) for (i=0;i<int(n);++i)#define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)#define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)#define REP_1_N(i, n) for (i=1;i<=int(n);++i)#define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)#define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)/** define-useful **/#define clr(x,a) memset(x,a,sizeof(x))#define sz(x) int(x.size())#define see(x) cerr<<#x<<" "<<x<<endl#define se(x) cerr<<" "<<x#define pb push_back#define mp make_pair/** test **/#define Display(A, n, m) { \ REP(i, n){ \ REP(j, m) cout << A[i][j] << " "; \ cout << endl; \ } \}#define Display_1(A, n, m) { \ REP_1(i, n){ \ REP_1(j, m) cout << A[i][j] << " "; \ cout << endl; \ } \}using namespace std;/** typedef **/typedef long long LL;/** Add - On **/const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };const int MOD = 1000000007;const int INF = 0x3f3f3f3f;const long long INFF = 1LL << 60;const double EPS = 1e-9;const double OO = 1e15;const double PI = acos(-1.0); //M_PI;---
---------------
二、图论
---
1 建图
---
const int maxn=111111;const int maxm=511111;int n,m;struct EDGENODE{ int to; int w; int next;};struct SGRAPH{ int head[maxn]; EDGENODE edges[maxm]; int edge; void init() { clr(head,-1); edge=0; } void addedge(int u,int v,int c=0) { edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; }}solver;---
2 最短路
---
2.1 堆优化的dijkstra
---
const int maxn=11111;const int maxm=1111111;struct EdgeNode{ int to; int w; int next;};struct HeapNode{ int d,u; bool operator<(const HeapNode& rhs) const{ return d>rhs.d; }};struct Dijkstra{ EdgeNode edges[maxm]; int head[maxn]; int edge,n; void init(int n){ this->n=n; memset(head,-1,sizeof(head)); edge=0; } void addedges(int u,int v,int c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } bool done[maxn]; int dis[maxn]; int pre[maxn]; void dijkstra(int s){ priority_queue<HeapNode>que; for (int i=0;i<n;i++) dis[i]=INF; dis[s]=0; memset(done,0,sizeof(done)); que.push((HeapNode){0,s}); while (!que.empty()){ HeapNode x=que.top(); que.pop(); int u=x.u; if (done[u]) continue; done[u]=true; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; int w=edges[i].w; if (dis[v]>dis[u]+w){ dis[v]=dis[u]+w; pre[v]=u; que.push((HeapNode){dis[v],v}); } } } }}solver;
---
2.2 队列优化的Bellman-Ford
---
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <vector>#include <cmath>#include <queue>using namespace std;const int INF=0x3f3f3f3f;const int maxm=111111;const int maxn=11111;struct EdgeNode{ int to; int w; int next;};struct BellmanFord{ EdgeNode edges[maxm]; int head[maxn],edge,n; bool vis[maxn]; int outque[maxn]; queue<int>que; int dis[maxn]; void addedge(int u,int v,int c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } void init(int n){ memset(head,-1,sizeof(head)); edge=0; this->n=n; } bool spfa(int s){ int u; for (int i=0;i<=n;i++) dis[i]=INF; memset(vis,0,sizeof(vis)); memset(outque,0,sizeof(outque)); while (!que.empty()) que.pop(); que.push(s); vis[s]=true; dis[s]=0; while (!que.empty()){ u=que.front(); que.pop(); vis[u]=false; outque[u]++; if (outque[u]>n) return false; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; int w=edges[i].w; if (dis[v]==INF||dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if (!vis[v]){ vis[v]=true; que.push(v); } } } } return true; }};
---
3 连通性
---
3.1 强连通分量Tarjan模板
---
const int maxn=111111;const int maxm=511111;int n,m;struct EDGENODE{ int to; int w; int next;};struct SGRAPH{ int head[maxn]; EDGENODE edges[maxm]; int edge; void init(int n) { clr(head,-1); edge=0; } void addedge(int u,int v,int c=0) { edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } int pre[maxn],lowlink[maxn],sccno[maxn],scc_cnt,dfs_clock; stack<int>stk; void dfs(int u) { pre[u]=lowlink[u]=++dfs_clock; stk.push(u); for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if (!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if (lowlink[u]==pre[u]){ scc_cnt++; int x; do{ x=stk.top(); stk.pop(); sccno[x]=scc_cnt; }while (x!=u); } } void find_scc(int n) { dfs_clock=scc_cnt=0; clr(sccno,0); clr(pre,0); while (!stk.empty()) stk.pop(); REP(i,n) if (!pre[i]) dfs(i); }}solver;---
3.2 双连通模板
---
const int maxn=1111;const int maxm=5111;int n,m;struct EDGENODE{ int to; int w; bool cut; int next;};struct SEDGE{ int u; int v; SEDGE(int uu=0,int vv=0){u=uu;v=vv;}};struct BCC_GRAPH{ int head[maxn]; EDGENODE edges[maxm]; int edge; void init() { clr(head,-1); edge=0; } void addedge(int u,int v,int c=0) { edges[edge].cut=0,edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } //BCC_Tarjan int dfn[maxn],low[maxn],bccno[maxn],dfs_clock,bcc_cnt; bool iscut[maxn]; vector<int>bcc[maxn]; stack<SEDGE>stk; int dfs(int u,int fa) { int lowu=dfn[u]=++dfs_clock; int child=0; for (int i=head[u];i!=-1;i=edges[i].next) { int v=edges[i].to; if (v==fa) continue; SEDGE e=SEDGE(u,v); if (!dfn[v]) { stk.push(e); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv); if (dfn[u]<=lowv) //cut 割点 { iscut[u]=true; //done 点双连通 bcc_cnt++; bcc[bcc_cnt].clear(); SEDGE x; do{ x=stk.top(); stk.pop(); if (bccno[x.u]!=bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u]=bcc_cnt; } if (bccno[x.v]!=bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v]=bcc_cnt; } }while (x.u!=u||x.v!=v); //over } if (dfn[u]<lowv) //cut 桥 { edges[i].cut=true; edges[i^1].cut=true; } } else if (dfn[v]<dfn[u]) { stk.push(e);//done lowu=min(lowu,dfn[v]); } } if (fa<0&&child==1) iscut[u]=0; low[u]=lowu; return lowu; } void find_bcc(int n) { while (!stk.empty()) stk.pop(); clr(dfn,0); clr(iscut,0); clr(bccno,0); dfs_clock=bcc_cnt=0; REP_1(i,n) { if (!dfn[i]) dfs(i,-1); } } //another int block[maxn]; int vis[maxn]; int b_num; void b_dfs(int u) { vis[u]=true; block[u]=b_num; for (int i=head[u];i!=-1;i=edges[i].next) { if (edges[i].cut) continue; int v=edges[i].to; if (!vis[v]) b_dfs(v); } } void find_block(int n) { //find_block 边双连通 clr(block,0); clr(vis,0); b_num=0; REP_1(i,n) { if (!vis[i]) { b_num++; b_dfs(i); } } }}solver;---
4 2-SAT
---
4.1 TwoSAT模板
---
const int maxn=2111;const int maxm=2111111;int n,m;struct EDGENODE{ int to; int next;};struct TWO_SAT{ int head[maxn*2]; EDGENODE edges[maxm*2]; int edge; int n; bool mark[maxn*2]; int S[maxn*2],c; void init(int n){ this->n=n; clr(mark,0); clr(head,-1); edge=0; } void addedge(int u,int v){ edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } // x = xval or y = yval void add_clause(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; addedge(x^1,y); addedge(y^1,x); } void add_con(int x,int xval){ x=x*2+xval; addedge(x^1,x); } bool dfs(int x){ if (mark[x^1]) return false; if (mark[x]) return true; mark[x]=true; S[c++]=x; for (int i=head[x];i!=-1;i=edges[i].next) if (!dfs(edges[i].to)) return false; return true; } bool solve(){ for (int i=0;i<n*2;i+=2) if (!mark[i]&&!mark[i+1]){ c=0; if (!dfs(i)){ while (c>0) mark[S[--c]]=false; if (!dfs(i+1)) return false; } } return true; }}TwoSAT;---
4.2 强连通Tarjan高效2-SAT
---
const int maxn=11111;const int maxm=2111111;int n,m;struct EDGENODE{ int to; int next;};struct TWO_SAT{ int head[maxn*2]; EDGENODE edges[maxm*2]; int edge; int n; void init(int n){ this->n=2*n; clr(head,-1); edge=0; } void addedge(int u,int v){ edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } // x = xval or y = yval void add_clause(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; addedge(x^1,y); addedge(y^1,x); } //x=xval void add_con(int x,int xval){ x=x*2+xval; addedge(x^1,x); } // void add_self(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; addedge(x,y); } int pre[maxn],lowlink[maxn],sccno[maxn],scc_cnt,dfs_clock; stack<int>stk; void dfs(int u) { pre[u]=lowlink[u]=++dfs_clock; stk.push(u); for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if (!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if (lowlink[u]==pre[u]){ scc_cnt++; int x; do{ x=stk.top(); stk.pop(); sccno[x]=scc_cnt; }while (x!=u); } } void find_scc(int n) { dfs_clock=scc_cnt=0; clr(sccno,0); clr(pre,0); while (!stk.empty()) stk.pop(); REP(i,n) if (!pre[i]) dfs(i); } bool solve(){ find_scc(n); for (int i=0;i<n;i+=2){ if (sccno[i]==sccno[i^1]) return false; } return true; }}TwoSAT;---
5 网络流
---
5.1 最大流模板Dinic
---
const int INF = 0x3f3f3f3f;const int maxm=11111;const int maxn=2222;struct edgenode{ int to,flow,next;};struct Dinic { int node,src,dest,edge; int head[maxn],work[maxn],dis[maxn],q[maxn]; edgenode edges[maxm]; void prepare(int _node,int _src,int _dest){ node=_node,src=_src,dest=_dest; memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v,int c){ edges[edge].flow=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; edges[edge].flow=0,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++; } bool Dinic_bfs() { int i,u,v,l,r=0; for (i=0; i<node; i++) dis[i]=-1; dis[q[r++]=src]=0; for (l=0; l<r; l++){ for (i=head[u=q[l]]; i!=-1; i=edges[i].next){ if (edges[i].flow&&dis[v=edges[i].to]<0){ dis[q[r++]=v]=dis[u]+1; if (v==dest) return true; } } } return false; } int Dinic_dfs(int u,int exp){ if (u==dest) return exp; for (int &i=work[u],v,tmp; i!=-1; i=edges[i].next){ if (edges[i].flow&&dis[v=edges[i].to]==dis[u]+1&& (tmp=Dinic_dfs(v,min(exp,edges[i].flow)))>0){ edges[i].flow-=tmp; edges[i^1].flow+=tmp; return tmp; } } return 0; } int Dinic_flow(){ int i,ret=0,delta; while (Dinic_bfs()){ for (i=0; i<node; i++) work[i]=head[i]; while ( delta=Dinic_dfs(src,INF) ) ret+=delta; } return ret; }}solver;
---
5.2 最小费用最大流
---
const int INF=0x3f3f3f3f;//无穷大const int maxm=1111111;//边的最大数量,为原图的两倍const int maxn=2222;//点的最大数量struct edgenode{ int to;//边的指向 int flow;//边的容量 int cost;//边的费用 int next;//链表的下一条边};struct MinCost{ edgenode edges[maxm]; int node,src,dest,edge;//node节点数,src源点,dest汇点,edge边数 int head[maxn],p[maxn],dis[maxn],q[maxn],vis[maxn];//head链表头,p记录可行流上节点对应的反向边,dis计算距离 void prepare(int _node=0,int _src=0,int _dest=0){ node=_node,src=_src,dest=_dest; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); edge=0; } void addedge(int u,int v,int f,int c){ printf("u=%d v=%d f=%d c=%d\n",u,v,f,c); edges[edge].flow=f;edges[edge].cost=c;edges[edge].to=v; edges[edge].next=head[u];head[u]=edge++; edges[edge].flow=0;edges[edge].cost=-c;edges[edge].to=u; edges[edge].next=head[v];head[v]=edge++; } bool spfa(){ int i,u,v,l,r=0,tmp; for (i=0;i<node;i++) dis[i]=INF; dis[q[r++]=src]=0; p[src]=p[dest]=-1; for (l=0;l!=r;((++l>=maxn)?l=0:l)){ for (i=head[u=q[l]],vis[u]=false;i!=-1;i=edges[i].next){ if (edges[i].flow&&dis[v=edges[i].to]>(tmp=dis[u]+edges[i].cost)){ dis[v]=tmp; p[v]=i^1; if (vis[v]) continue; vis[q[r++]=v]=true; if (r>=maxn) r=0; } } } return p[dest]>=0; } int spfaflow(){ int i,ret=0,delta; while (spfa()){//按记录原路返回求流量 for (i=p[dest],delta=INF;i>=0;i=p[edges[i].to]){ delta=min(delta,edges[i^1].flow); } for (int i=p[dest];i>=0;i=p[edges[i].to]){ edges[i].flow+=delta; edges[i^1].flow-=delta; } ret+=delta*dis[dest]; } return ret; } void output(int u){ cout<<u<<endl; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (edges[i].flow==0&&((i&1)==0)) output(v); } }}solver;
-------------
6 无向图最小割 (New)
-----
struct StoerWagner{ int mat[maxn][maxn]; int dis[maxn]; int S,T; int n; bool vis[maxn],del[maxn]; void init(int n){ memset(mat,0,sizeof(mat)); this->n=n; } void addedge(int u,int v,int c){ mat[u][v]+=c; mat[v][u]+=c; } int search(int ct){ int tmp,mx,cut; memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); T=S=-1; for (int i=0;i<n-ct;i++){ mx=-1; for (int j=0;j<n;j++){ if (!vis[j]&&!del[j]&&dis[j]>mx){ mx=dis[j]; tmp=j; } } S=T; T=tmp; cut=mx; vis[T]=true; for (int j=0;j<n;j++){ if (!vis[j]&&!del[j]){ dis[j]+=mat[T][j]; } } } return cut; } int minimumCut(){ int ans=INF; memset(del,0,sizeof(del)); for (int i=0;i<n-1;i++){ int cut=search(i); if (cut<ans) ans=cut; if (ans==0) return 0; del[T]=true; for (int j=0;j<n;j++){ if (!del[j]){ mat[S][j]+=mat[T][j]; mat[j][S]+=mat[T][j]; } } } return ans; }};
----------------------
7 倍增LCA
------------------------
void preprocess(){ for (int i=1;i<=n;i++){ anc[i][0]=fa[i]; maxCost[i][0]=cost[i]; for (int j=1;(1<<j)<n;j++) anc[i][j]=-1; } for (int j=1;(1<<j)<n;j++){ for (int i=1;i<=n;i++){ if (anc[i][j-1]!=-1){ int a=anc[i][j-1]; anc[i][j]=anc[a][j-1]; maxCost[i][j]=max(maxCost[i][j-1],maxCost[a][j-1]); } } } } int query(int p,int q){ int log; if (L[p]<L[q]) swap(p,q); for (log=1;(1<<log)<=L[p];log++);log--; int ans=-INF; for (int i=log;i>=0;i--){ if (L[p]-(1<<i)>=L[q]){ ans=max(ans,maxCost[p][i]); p=anc[p][i]; } } if (p==q) return ans; for (int i=log;i>=0;i--){ if (anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){ ans=max(ans,maxCost[p][i]); p=anc[p][i]; ans=max(ans,maxCost[q][i]); q=anc[q][i]; } } ans=max(ans,cost[p]); ans=max(ans,cost[q]); return ans; }
8 树
8.1 树的重心
class CenterTree{private: int sz[maxn]; void dfs(int u,int pa){ sz[u]=1; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (v==pa) continue; //if (tree[v].visit) continue; dfs(v,u); sz[u]+=sz[v]; } }public: int getCenter(int x){ int p=0; dfs(x,p); int cap=sz[x]/2; bool found=true; while (found){ found=false; for (int i=head[x];i!=-1;i=edges[i].next){ int y=edges[i].to; //if (tree[y].visit) continue; if (y!=p&&sz[y]>cap){ found=true; p=x; x=y; break; } } } return x; }}coder;
8.2 树的中心
class TreeCenter{private: int f[maxn]; int dp[maxn]; int M,MM; int dfs(int u,int pa){ int m1=0,m2=0; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (v==pa) continue; int t=dfs(v,u); if (t>m1){ m2=m1; m1=t; f[u]=i; } else if (t>m2){ m2=t; } } if (M<m1+m2) MM=u,M=m1+m2; dp[u]=m1; return dp[u]+1; }public: int getCenter(int n){ M=-1; dfs(1,-1); if (M&1){ while (dp[MM]*2>M+1) MM=edges[f[MM]].to; //int E=f[MM]; addedge(MM,n+1); addedge(n+1,MM); addedge(edges[f[MM]].to,n+1); addedge(n+1,edges[f[MM]].to); MM=n+1; } else{ //int E=0; while (dp[MM]*2>M) MM=edges[f[MM]].to; } return MM; }}solver;
---------------
三、数据结构
---
1 树堆Treap
---
名次树 启发式合并
#include <iostream>#include <ctime>#include <cstdlib>#include <cstdio>#include <cstring>#include <vector>using namespace std;struct Node{ Node* ch[2];//左右子树 int fix;//优先级。数值越大,优先级越高 int key; int size;//以它为根的子树的总结点数 bool operator<(const Node& rhs) const { return fix<rhs.fix; } int cmp(int x) const{ if (x==key) return -1; return x<key?0:1; } //名次树 void maintain(){ size=1; if (ch[0]!=NULL) size+=ch[0]->size; if (ch[1]!=NULL) size+=ch[1]->size; }};struct Treap{ Node* root; Treap(){ srand(time(0)); root=NULL; } void removetree(Node* &t){ if (t->ch[0]!=NULL) removetree(t->ch[0]); if (t->ch[1]!=NULL) removetree(t->ch[1]); delete t; t=NULL; } void clear(){ srand(time(0)); removetree(root); } Node* newNode(int v){ Node* t=new Node; t->key=v; t->ch[0]=t->ch[1]=NULL; t->fix=rand(); t->size=1; return t; } //d=0代表左旋,d=1代表右旋 void rotate(Node* &o,int d){ Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(); k->maintain(); o=k; } //在以o为根的子树中插入键值x,修改o void insert(Node* &o,int x){ if (o==NULL) o=newNode(x); else{ int d=o->cmp(x); if (d==-1) d=1; insert(o->ch[d],x); if (o->ch[d]>o) rotate(o,d^1); } o->maintain(); } void remove(Node* &o,int x){ int d=o->cmp(x); if (d==-1){ Node* u=o; if (o->ch[0]!=NULL&&o->ch[1]!=NULL){ int d2=(o->ch[0]>o->ch[1]?1:0); rotate(o,d2); remove(o->ch[d2],x); }else{ if (o->ch[0]==NULL) o=o->ch[1]; else if (o->ch[1]==NULL) o=o->ch[0]; delete u; } } else remove(o->ch[d],x); if (o!=NULL) o->maintain(); } bool find(Node* o,int x){ while (o!=NULL){ int d=o->cmp(x); if (d==-1) return 1; else o=o->ch[d]; } return 0; } //第k大的值 int kth(Node* o,int k){ if (o==NULL||k<=0||k>o->size) return 0; int s=(o->ch[1]==NULL?0:o->ch[1]->size); if (k==s+1) return o->key; else if (k<=s) return kth(o->ch[1],k); else return kth(o->ch[0],k-s-1); } void merge(Node* &src){ if (src->ch[0]!=NULL) merge(src->ch[0]); if (src->ch[1]!=NULL) merge(src->ch[1]); insert(root,src->key); delete src; src=NULL; }};
---
2 伸展树Splay
---
2.1 My Splay v1.0
---
/********************************************************************************** Splay Tree v1.0 索引 Node: void addIt(int ad) 区间添加ad void revIt() 区间翻转 void upd() 更新结点,子树改变后使用 void pushdown() 向下传递懒惰标记 Splay: Node* newNode(int v,Node* f) 构造一个val值为v的节点,父节点为f, Node* build(int l,int r,Node* f) 构造区间[l,r],父节点为f; void rotate(Node* t,int d) 左旋右旋 void splay(Node* t,Node* f) 将结点t伸展到f void select(int k) 返回第k个节点并伸展到f,不计虚拟结点 Node*&get(int l, int r) 返回区间[l,r],即l-1旋转到根,r+1旋转到根的右儿子 void reverse(int l,int r) 翻转区间[l,r] void split(int l,int r,Node*&s1) 将区间[l,r]剪切到s1 void cut(int l,int r) 将区间[l,r]剪切到序列尾部 void init(int n) 构造区间[1,n]并初始化 void show(Node* rt) 输出树rt的中序遍历,debug用 void output(int l,int r) 输出并伸展区间[l,r],复杂度较高待优化 注意: 每种修改操作(插入、删除、修改和翻转)过后, 要将修改的结点(即根结点右子结点的左子结点)Splay到根的位置。 删除操作要回收空间,可以人工压栈回收结点指针**********************************************************************************/#include <iostream>#include <ctime>#include <cstdlib>#include <cstdio>#include <cstring>#include <vector>using namespace std;const int MAX_N = 150000 + 10;const int INF = ~0U >> 1;struct Node{ Node *ch[2],*pre;//左右子树,父节点 int val;//关键字 int size;//以它为根的子树的总结点数 int mx;//最大值 int add;//添加标记 bool rev;//翻转标记 Node(){ size=0; val=mx=-INF; add=0; } void addIt(int ad){ add+=ad; mx+=ad; val+=ad; } void revIt(){ rev^=1; } void upd(){ size=ch[0]->size+ch[1]->size+1; mx=max(val,max(ch[0]->mx,ch[1]->mx)); } void pushdown();}Tnull,*null=&Tnull;void Node::pushdown(){ if (add!=0){ for (int i=0;i<2;++i) if (ch[i]!=null) ch[i]->addIt(add); add = 0; } if (rev){ swap(ch[0],ch[1]); for (int i=0;i<2;i++) if (ch[i]!=null) ch[i]->revIt(); rev = 0; }}struct Splay{ Node nodePool[MAX_N],*cur;//内存分配 Node* root;//根 Splay(){ cur=nodePool; root=null; } //清空内存,init()调用 void clear(){ cur=nodePool; root=null; } //新建节点,build()用 Node* newNode(int v,Node* f){ cur->ch[0]=cur->ch[1]=null; cur->size=1; cur->val=v; cur->mx=v; cur->add=0; cur->rev=0; cur->pre=f; return cur++; } //构造区间[l,r]中点m,init()使用 Node* build(int l,int r,Node* f){ if(l>r) return null; int m=(l+r)>>1; Node* t=newNode(m,f); t->ch[0]=build(l,m-1,t); t->ch[1]=build(m+1,r,t); t->upd(); return t; } //旋转操作,c=0表示左旋,c=1表示右旋 void rotate(Node* x,int c){ Node* y=x->pre; y->pushdown(); x->pushdown(); //先将y结点的标记向下传递(因为y在上面) y->ch[!c]=x->ch[c]; if (x->ch[c]!=null) x->ch[c]->pre=y; x->pre=y->pre; if (y->pre!=null) { if (y->pre->ch[0]==y) y->pre->ch[0]=x; else y->pre->ch[1]=x; } x->ch[c]=y; y->pre=x; y->upd();//维护y结点 if (y==root) root=x; } //Splay操作,表示把结点x转到结点f的下面 void splay(Node* x,Node* f){ x->pushdown();//下传x的标记 while (x->pre!=f){ if (x->pre->pre==f){//父节点的父亲为f,执行单旋 if (x->pre->ch[0]==x) rotate(x,1); else rotate(x,0); }else{ Node *y=x->pre,*z=y->pre; if (z->ch[0]==y){ if (y->ch[0]==x) rotate(y,1),rotate(x,1);//一字型旋转 else rotate(x,0),rotate(x,1);//之字形旋转 }else{ if (y->ch[1]==x) rotate(y,0),rotate(x,0);//一字型旋转 else rotate(x,1),rotate(x,0);//之字形旋转 } } } x->upd();//最后再维护X结点 } //找到处在中序遍历第k个结点,并将其旋转到结点f的下面 void select(int k,Node* f){ int tmp; Node* x=root; x->pushdown(); k++;//空出虚拟节点 for(;;){ x->pushdown(); tmp=x->ch[0]->size; if (k==tmp+1) break; if (k<=tmp) x=x->ch[0]; else{ k-=tmp+1; x=x->ch[1]; } } splay(x,f); } //选择[l,r] Node*&get(int l, int r){ select(l-1,null); select(r+1,root); return root->ch[1]->ch[0]; } //翻转[l,r] void reverse(int l,int r){ Node* o=get(l,r); o->rev^=1; splay(o,null); } //剪切出[l,r]到s1 void split(int l,int r,Node*&s1) { Node* tmp=get(l,r); s1=tmp; root->ch[1]->ch[0]=null; splay(root->ch[1],null); } void cut(int l,int r) { Node* tmp; split(l,r,tmp); select(root->size-1,null); select(root->size-2,root); root->ch[0]->ch[1]=tmp; tmp->pre=root->ch[0]; splay(tmp,null); } //初始化 void init(int n){ clear(); root=newNode(0,null); root->ch[1]=newNode(n+1,root); root->ch[1]->ch[0]=build(1,n,root->ch[1]); splay(root->ch[1]->ch[0],null); } //输出中序遍历,debug用 void show(Node* rt){ if (rt==null) return; if (rt->ch[0]!=null) show(rt->ch[0]); cerr<<"rt="<<rt->val; if (rt->ch[0]!=null) cerr<<" l="<<rt->ch[0]->val; if (rt->ch[1]!=null) cerr<<" r="<<rt->ch[1]->val; if (rt->pre !=null) cerr<<" pre="<<rt->pre->val; cerr<<endl; if (rt->ch[1]!=null) show(rt->ch[1]); } //按序输出 void output(int l,int r){ for (int i=l;i<=r;i++){ select(i,null); cout<<root->val<<endl; } //cout<<endl; }}T;int main(){ int n,m,a,b; while (~scanf("%d%d",&n,&m)) { T.init(n); while (m--) { scanf("%d%d",&a,&b); if (b<a) swap(a,b); T.reverse(a,b); T.cut(a,b); } T.output(1,n); } return 0;}---
2.2 BYVoid's Splay
---
/* * Problem: NOI2005 sequence * Author: Guo Jiabao * Time: 2009.5.30 14:19 * State: Solved * Memo: 伸展树*/#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>using namespace std;const int MAXN=2850003,MAXL=500001,INF=1001;struct SplayTree{ struct SplayNode { SplayNode *c[2],*f; int value,size,sum,maxsum,mls,mrs; bool rev,same; }*root,*null,*lb,*rb,SS[MAXN]; int SC; SplayNode * NewNode(int value,SplayNode *f) { SplayNode *e=SS+ ++SC; e->value=value; e->size=1;e->f=f; e->sum=e->maxsum=e->mls=e->mrs=value; e->same=e->rev=false; e->c[0]=e->c[1]=null; return e; } inline int max(int a,int b){return a>b?a:b;} void update(SplayNode *p) { if (p==null) return; p->size = p->c[0]->size + p->c[1]->size + 1; p->sum = p->c[0]->sum + p->c[1]->sum + p->value; p->mls = p->c[0]->mls; p->mls = max( p->mls , p->c[0]->sum + p->value); p->mls = max( p->mls , p->c[0]->sum + p->value + p->c[1]->mls ); p->mrs = p->c[1]->mrs; p->mrs = max( p->mrs , p->c[1]->sum + p->value); p->mrs = max( p->mrs , p->c[1]->sum + p->value + p->c[0]->mrs ); p->maxsum = p->value; p->maxsum = max( p->maxsum , p->c[0]->maxsum ); p->maxsum = max( p->maxsum , p->c[1]->maxsum ); p->maxsum = max( p->maxsum , p->c[0]->mrs + p->value ); p->maxsum = max( p->maxsum , p->c[1]->mls + p->value ); p->maxsum = max( p->maxsum , p->c[0]->mrs + p->c[1]->mls + p->value ); } void pushdown(SplayNode *p) { if (p==null) return; if (p->rev) { p->rev=false; SplayNode *q=p->c[0]; p->c[0]=p->c[1]; p->c[1]=q; p->c[0]->rev = !p->c[0]->rev; p->c[1]->rev = !p->c[1]->rev; int t=p->mls; p->mls=p->mrs; p->mrs=t; } if (p->same) { p->same=false; p->c[0]->same=p->c[1]->same=true; p->c[0]->value=p->c[1]->value=p->value; p->sum = p->maxsum = p->mls = p->mrs = p->value * p->size; if (p->value < 0) p->maxsum = p->mls = p->mrs = p->value; } } void rotate(SplayNode *x,int o)//Zig o=0 Zag o=1 { SplayNode *y=x->f; pushdown(x->c[0]); pushdown(x->c[1]); pushdown(y->c[!o]); y->c[o] = x->c[!o]; y->c[o]->f=y; x->f = y->f; if (y->f->c[0]==y) y->f->c[0]=x; else y->f->c[1]=x; y->f=x; x->c[!o]=y; update(y); update(x); if (root==y) root=x; } void splay(SplayNode *x,SplayNode *y) { pushdown(x); while (x->f!=y) { if (x->f->f==y) { if (x->f->c[0]==x) rotate(x,0); else rotate(x,1); } else if (x->f->f->c[0] == x->f) { if (x->f->c[0]==x) rotate(x->f,0),rotate(x,0); else rotate(x,1),rotate(x,0); } else { if (x->f->c[1]==x) rotate(x->f,1),rotate(x,1); else rotate(x,0),rotate(x,1); } } } void select(int k,SplayNode *y) { SplayNode *x=root; pushdown(x); for (;k != x->c[0]->size + 1;) { if (k <= x->c[0]->size) x=x->c[0]; else { k-=x->c[0]->size + 1; x=x->c[1]; } pushdown(x); } splay(x,y); } void Insert(int pos,int tot,int *C) { SplayNode *z,*t; z=t=NewNode(C[1],null); for (int i=2;i<=tot;i++) z=z->c[1]=NewNode(C[i],z); select(pos+1,null); select(pos+2,root); root->c[1]->c[0] = t; t->f=root->c[1]; splay(z,null); } void Delete(int pos,int tot) { select(pos,null); select(pos+tot+1,root); root->c[1]->c[0] = null; splay(root->c[1],null); } void MakeSame(int pos,int tot,int value) { select(pos,null); select(pos+tot+1,root); root->c[1]->c[0]->same=true; root->c[1]->c[0]->value=value; splay(root->c[1]->c[0],null); } void Reverse(int pos,int tot) { select(pos,null); select(pos+tot+1,root); root->c[1]->c[0]->rev=!root->c[1]->c[0]->rev; splay(root->c[1]->c[0],null); } int GetSum(int pos,int tot) { select(pos,null); select(pos+tot+1,root); pushdown(root->c[1]->c[0]); return root->c[1]->c[0]->sum; } int MaxSum() { pushdown(root); update(root); return root->maxsum; } void init() { SC=-1; null=0; null=NewNode(-INF,0); null->size=0; lb=root=NewNode(-INF,null); rb=root->c[1]=NewNode(-INF,root); null->sum = lb->sum = rb->sum=0; update(root); }}Splay;int N,M,C[MAXL],pos,i,j,A;char Ctrl[20];int main(){ freopen("seq2005.in","r",stdin); freopen("seq2005.out","w",stdout); Splay.init(); scanf("%d%d",&N,&M); for (i=1;i<=N;i++) scanf("%d",&C[i]); Splay.Insert(0,N,C); for (i=1;i<=M;i++) { scanf("%s",Ctrl); switch (Ctrl[0]) { case 'I': scanf("%d%d",&pos,&N); for (j=1;j<=N;j++) scanf("%d",&C[j]); Splay.Insert(pos,N,C); break; case 'D': scanf("%d%d",&pos,&N); Splay.Delete(pos,N); break; case 'R': scanf("%d%d",&pos,&N); Splay.Reverse(pos,N); break; case 'G': scanf("%d%d",&pos,&N); A=Splay.GetSum(pos,N); printf("%d\n",A); break; case 'M': if (Ctrl[2]=='K') { scanf("%d%d%d",&pos,&N,&C[0]); Splay.MakeSame(pos,N,C[0]); } else printf("%d\n",Splay.MaxSum()); break; } } return 0;}
---
3 树状数组
---
struct BIT{ int n; int tree[maxn]; void init(int n){ this->n=n; memset(tree,0,sizeof(tree)); } int lowbit(int x){ return x&(-x); } void add(int x,int val){ for (int i=x;i<=n;i+=lowbit(i)) tree[i]+=val; } int query(int x){ int ret=0; for (int i=x;i>0;i-=lowbit(i)) ret+=tree[i]; return ret; } //离散 p=lower_bound(b+1,b+n+1,a[i])-b; //逆序数 x=(i-1)-query(p);add(p,1);};
---
4 线段树
---
4.1 单点更新
---
const int MAXN=255111;struct SegmentTree{ int num[MAXN]; struct Tree{ int l; int r; int min; }; Tree tree[MAXN*4]; void push_up(int root){ tree[root].min=min(tree[root<<1].min,tree[root<<1|1].min); } void build(int root,int l,int r){ tree[root].l=l; tree[root].r=r; if(tree[root].l==tree[root].r){ tree[root].min=num[l]; return; } int mid=(l+r)/2; build(root<<1,l,mid); build(root<<1|1,mid+1,r); push_up(root); } void update(int root,int pos,int val){ if(tree[root].l==tree[root].r){ tree[root].min=val; return; } int mid=(tree[root].l+tree[root].r)/2; if(pos<=mid) update(root<<1,pos,val); else update(root<<1|1,pos,val); push_up(root); } int query(int root,int L,int R){ if(L<=tree[root].l&&R>=tree[root].r) return tree[root].min; int mid=(tree[root].l+tree[root].r)/2,ret=INF; if(L<=mid) ret=min(ret,query(root<<1,L,R)); if(R>mid) ret=min(ret,query(root<<1|1,L,R)); return ret; } void init(int n,int d){ for (int i=1;i<=n;i++) num[i]=d; build(1,1,n); }};
---
4.2 区间维护
---
const int INF=0x3f3f3f;const int MAXN=10000;struct SegTree{ int num[MAXN]; int _min,_max,_sum; struct Tree{ int l; int r; int max; int min; int sum; int add; int set; }; Tree tree[MAXN*4]; void push_up(int root){ tree[root].max=max(tree[root<<1].max,tree[root<<1|1].max); tree[root].min=min(tree[root<<1].min,tree[root<<1|1].min); tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum; } void push_down(int root){ if (tree[root].set!=-1){ if (tree[root].l!=tree[root].r){ //传递懒惰标记 tree[root<<1].add=tree[root<<1|1].add=0; tree[root<<1].set=tree[root<<1|1].set=tree[root].set; //最更新大值 tree[root<<1].max=tree[root<<1|1].max=tree[root].set; //更新最小值 tree[root<<1].min=tree[root<<1|1].min=tree[root].set; //更新区间和 tree[root<<1].sum=(tree[root<<1].r-tree[root<<1].l+1)*tree[root].set; tree[root<<1|1].sum=(tree[root<<1|1].r-tree[root<<1|1].l+1)*tree[root].set; } tree[root].set=-1; } if (tree[root].add>0){ if (tree[root].l!=tree[root].r){ //传递懒惰标记 tree[root<<1].add+=tree[root].add; tree[root<<1|1].add+=tree[root].add; //更新最大值 tree[root<<1].max+=tree[root].add; tree[root<<1|1].max+=tree[root].add; //更新最小值 tree[root<<1].min+=tree[root].add; tree[root<<1|1].min+=tree[root].add; //更新区间和 tree[root<<1].sum+=(tree[root<<1].r-tree[root<<1].l+1)*tree[root].add; tree[root<<1|1].sum+=(tree[root<<1|1].r-tree[root<<1|1].l+1)*tree[root].add; } tree[root].add=0; } } void build(int root,int l,int r){ tree[root].l=l; tree[root].r=r; if(tree[root].l==tree[root].r){ tree[root].max=num[l]; tree[root].min=num[l]; tree[root].sum=num[l]; tree[root].add=0; tree[root].set=-1; return; } int mid=(l+r)/2; build(root<<1,l,mid); build(root<<1|1,mid+1,r); push_up(root); } void update_add(int root,int L,int R,int val){ if(L<=tree[root].l&&R>=tree[root].r){ tree[root].add+=val; tree[root].max+=val; tree[root].min+=val; tree[root].sum+=(tree[root].r-tree[root].l+1)*val; return; } push_down(root); int mid=(tree[root].l+tree[root].r)/2; if(L<=mid) update_add(root<<1,L,R,val); if(R>mid) update_add(root<<1|1,L,R,val); push_up(root); } void update_set(int root,int L,int R,int val){ if(L<=tree[root].l&&R>=tree[root].r){ tree[root].set=val; tree[root].add=0; tree[root].max=val; tree[root].min=val; tree[root].sum=(tree[root].r-tree[root].l+1)*val; return; } push_down(root); int mid=(tree[root].l+tree[root].r)/2; if(L<=mid) update_set(root<<1,L,R,val); if (R>mid) update_set(root<<1|1,L,R,val); push_up(root); } void query(int root,int L,int R){ if(L<=tree[root].l&&R>=tree[root].r){ _min=min(_min,tree[root].min); _max=max(_max,tree[root].max); _sum+=tree[root].sum; return; } push_down(root); int mid=(tree[root].l+tree[root].r)/2; if(L<=mid) query(root<<1,L,R); if(R>mid) query(root<<1|1,L,R); }};
---
---
5 并查集
---
int pa[maxn];void makeset(int n){ for (int i=0;i<=n;i++) pa[i]=i;}int findset(int x){ if (x!=pa[x]) pa[x]=findset(pa[x]); return pa[x];}void unionset(int x,int y){ x=findset(x); y=findset(y); if (x!=y) pa[x]=y;}
---
6 RMQ
---
6.1 取最小值
---
int d[maxn][20]; //元素从1编号到n void RMQ_init(int A[],int n){ for (int i=1;i<=n;i++) d[i][0]=A[i]; for (int j=1;(1<<j)<=n;j++) for (int i=1;i+(1<<j)-1<=n;i++) d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]); } int RMQ(int L,int R){ int k=0; while ((1<<(k+1))<=R-L+1) k++; return min(d[L][k],d[R-(1<<k)+1][k]); }
---
6.2 取最小值的下标
---
int d[maxn][20]; //元素从1编号到n void makeRmqIndex(int A[],int n){ for(int i=1;i<=n;i++) d[i][0]=i; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) d[i][j] = A[d[i][j-1]] < A[d[i+(1<<(j-1))][j-1]]? d[i][j-1]:d[i+(1<<(j-1))][j-1]; } int rmqIndex(int L,int R,int A[]) { int k=0; while ((1<<(k+1))<=R-L+1) k++; return A[d[L][k]]<A[d[R-(1<<k)+1][k]]? d[L][k]:d[R-(1<<k)+1][k]; }
---
7 LCA的RMQ解法
---
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int INF=0x3f3f3f;const int maxn=111111;const int maxm=111111;int n,m;struct EDGENODE{ int to; int w; int next;};struct SGRAPH{ int head[maxn]; EDGENODE edges[maxm]; int edge; void init(){ memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v,int c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } //------------ int d[maxn][20]; //元素从1编号到n void makeRmqIndex(int A[],int n){ for(int i=1;i<=n;i++) d[i][0]=i; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) d[i][j] = A[d[i][j-1]] < A[d[i+(1<<(j-1))][j-1]]? d[i][j-1]:d[i+(1<<(j-1))][j-1]; } int rmqIndex(int L,int R,int A[]) { int k=0; while ((1<<(k+1))<=R-L+1) k++; return A[d[L][k]]<A[d[R-(1<<k)+1][k]]? d[L][k]:d[R-(1<<k)+1][k]; } //--------------------- int E[maxn*2],R[maxn],D[maxn*2],mn; void dfs(int u,int p,int d){ E[++mn]=u; D[mn]=d; R[u]=mn; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (v==p) continue; dfs(v,u,d+1); E[++mn]=u; D[mn]=d; } } void LCA_init(){ mn=0; memset(R,0,sizeof(R)); dfs(1,-1,1); makeRmqIndex(D,mn); getd(1,-1,0); } int LCA(int u,int v){ if (R[u]>=R[v]) return E[rmqIndex(R[v],R[u],D)]; else return E[rmqIndex(R[u],R[v],D)]; } //-------------------- int deep[maxn]; void getd(int u,int p,int w){ deep[u]=w; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (v==p) continue; getd(v,u,w+edges[i].w); } } int getDis(int u,int v){ int lca=LCA(u,v); return deep[u]+deep[v]-deep[lca]*2; } int done(int x,int y,int z){ int ans=INF,res=0; int lca1,lca2; lca1=LCA(x,y); res=deep[x]+deep[y]-deep[lca1]*2; lca2=LCA(lca1,z); res+=deep[lca1]+deep[z]-deep[lca2]*2; ans=min(ans,res); lca1=LCA(x,z); res=deep[x]+deep[z]-deep[lca1]*2; lca2=LCA(lca1,y); res+=deep[lca1]+deep[y]-deep[lca2]*2; ans=min(ans,res); lca1=LCA(y,z); res=deep[y]+deep[z]-deep[lca1]*2; lca2=LCA(lca1,x); res+=deep[lca1]+deep[x]-deep[lca2]*2; ans=min(ans,res); return ans; }}solver;---
---------------
四、字符串
---
1 字典树Trie
---
const int CHARSET = 26;const int MAX_N_NODES = int(3e5) + 10;struct TrieNode{ TrieNode* next[CHARSET]; int num;//记录是不是一个单词 int value;//记录单词出现的次数 TrieNode(){ memset(next,0,sizeof(next)); value=0; num=0; } void clear(){ memset(next,0,sizeof(next)); value=0; num=0; }}*root;TrieNode nodePool[MAX_N_NODES],*cur;TrieNode* newNode(){TrieNode* t = cur++;t->clear();return t;}void trieInit() {cur=nodePool;root=newNode();}//插入:void insert(char* s){ TrieNode* p=root; int k=0; while(s[k]!='\0'){ if(!p->next[s[k]-'a']) p->next[s[k]-'a']=newNode(); p=p->next[s[k]-'a']; p->num++; k++; } p->value=1;}//查找int find(char* s){ TrieNode* p=root; int k=0; while(s[k]!='\0'&&p->next[s[k]-'a']){ p=p->next[s[k]-'a']; k++; } if(s[k]=='\0') return p->num; return 0;}//DP查找void dpfind(char* s,int pos){ TrieNode* p=root; int k=0; while(s[k]!='\0'&&p->next[s[k]-'a']){ p=p->next[s[k]-'a']; if (p->value==1){ //do something like dp... //f[pos+k+1]=(f[pos+k+1]+f[pos])%MOD; } k++; }}
---
f[0]=1;
for (int i=1;i<=l;i++)
if (f[i-1]) find(str+i,i-1);
---
2 扩展KMP
---
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int MM=100005;int next[MM],extand[MM];char S[MM],T[MM];void GetNext(const char *T){ int len=strlen(T),a=0; next[0]=len; while(a<len-1 && T[a]==T[a+1]) a++; next[1]=a; a=1; for(int k=2;k<len;k++){ int p=a+next[a]-1,L=next[k-a]; if( (k-1)+L >= p){ int j = (p-k+1)>0 ? (p-k+1) : 0; while(k+j<len && T[k+j]==T[j]) j++; next[k]=j; a=k; } else next[k]=L; }}void GetExtand(const char *S,const char *T){ GetNext(T); int slen=strlen(S),tlen=strlen(T),a=0; int MinLen = slen < tlen ? slen : tlen; while(a<MinLen && S[a]==T[a]) a++; extand[0]=a; a=0; for(int k=1;k<slen;k++){ int p=a+extand[a]-1, L=next[k-a]; if( (k-1)+L >= p){ int j= (p-k+1) > 0 ? (p-k+1) : 0; while(k+j<slen && j<tlen && S[k+j]==T[j]) j++; extand[k]=j; a=k; } else extand[k]=L; }}int main(){ while(scanf("%s%s",S,T)==2){ GetExtand(S,T); for(int i=0;i<strlen(T);i++) printf("%d ",next[i]); puts(""); for(int i=0;i<strlen(S);i++) printf("%d ",extand[i]); puts(""); } return 0;}---
3 Aho-Corasick自动机
---
const int CHARSET = 26;const int MAX_N_NODES = int(3e5) + 10;struct Aho_Corasick{ struct Node{ Node *next[CHARSET]; Node *fail; int count;//记录当前前缀是完整单词出现的个数 Node(){ memset(next,0,sizeof(next)); fail = NULL; count = 0; } void clear(){ memset(next,0,sizeof(next)); fail = NULL; count = 0; } }; Node *root; Node nodePool[MAX_N_NODES], *cur; Node* newNode(){ Node* t=cur++; t->clear(); return t; } void init(){ cur=nodePool; root=newNode(); } void insert(char *str){ Node* p=root; int i=0,index; while(str[i]){ index=str[i]-'a'; if(p->next[index]==NULL) p->next[index]=newNode(); p=p->next[index]; i++; } p->count++; } void build_ac_automation(){ int i; queue<Node*>Q; root->fail=NULL; Q.push(root); while(!Q.empty()){ Node* temp=Q.front(); Q.pop(); Node* p=NULL; for(i=0;i<CHARSET;i++){ if(temp->next[i]!=NULL){//寻找当前子树的失败指针 p = temp->fail; while(p!=NULL){ if(p->next[i]!=NULL){//找到失败指针 temp->next[i]->fail=p->next[i]; break; } p=p->fail; } if(p==NULL) temp->next[i]->fail=root;//无法获取,当前子树的失败指针为根 Q.push(temp->next[i]); } } } } int query(char *str){//询问str中包含n个关键字中多少种即匹配 int i=0,cnt=0,index; Node* p = root; while(str[i]){ index=str[i]-'a'; while(p->next[index]==NULL&&p!=root) p=p->fail;//失配 p=p->next[index]; if(p==NULL) p = root;//失配指针为根 Node* temp = p; while(temp!=root&&temp->count!=-1){//寻找到当前位置为止是否出现关键字 cnt+=temp->count; temp->count=-1; temp=temp->fail; } i++; } return cnt; }};
---
---4 后缀数组
---
const int maxn=3e5*2+10;/******************************************************************** 后缀数组 Suffix Array** INIT:solver.call_fun(char* s);** CALL: solver.lcp(int i,int j); //后缀i与后缀j的最长公共前缀** SP_USE: solver.LCS(char *s1,char* s2); //最长公共字串******************************************************************/struct SuffixArray{ int r[maxn]; int sa[maxn],rank[maxn],height[maxn]; int t[maxn],t2[maxn],c[maxn],n; int m;//模板长度 void init(char* s){ n=strlen(s); for (int i=0;i<n;i++) r[i]=int(s[i]); m=300; } int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } /** 字符要先转化为正整数 待排序的字符串放在r[]数组中,从r[0]到r[n-1],长度为n,且最大值小于m。 所有的r[i]都大于0,r[n]无意义算法中置0 函数结束后,结果放在sa[]数组中(名次从1..n),从sa[1]到sa[n]。s[0]无意义 **/ void build_sa(){ int i,k,p,*x=t,*y=t2; r[n++]=0; for (i=0;i<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[i]=r[i]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for (k=1,p=1;k<n;k*=2,m=p){ for (p=0,i=n-k;i<n;i++) y[p++]=i; for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; for (i=0;i<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[y[i]]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for (i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++; } n--; } /** height[2..n]:height[i]保存的是lcp(sa[i],sa[i-1]) rank[0..n-1]:rank[i]保存的是原串中suffix[i]的名次 **/ void getHeight(){ int i,j,k=0; for (i=1;i<=n;i++) rank[sa[i]]=i; for (i=0;i<n;i++){ if (k) k--; j=sa[rank[i]-1]; while (r[i+k]==r[j+k]) k++; height[rank[i]]=k; } } int d[maxn][20]; //元素从1编号到n void RMQ_init(int A[],int n){ for (int i=1;i<=n;i++) d[i][0]=A[i]; for (int j=1;(1<<j)<=n;j++) for (int i=1;i+j-1<=n;i++) d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]); } int RMQ(int L,int R){ int k=0; while ((1<<(k+1))<=R-L+1) k++; return min(d[L][k],d[R-(1<<k)+1][k]); } void LCP_init(){ RMQ_init(height,n); } int lcp(int i,int j){ if (rank[i]>rank[j]) swap(i,j); return RMQ(rank[i]+1,rank[j]); } void call_fun(char* s){ init(s);//初始化后缀数组 build_sa();//构造后缀数组sa getHeight();//计算height与rank LCP_init();//初始化RMQ } int LCS(char* s1,char* s2){ int p,ans; int l=strlen(s1); p=l; s1[l]='$'; s1[l+1]='\0'; strcat(s1,s2); call_fun(s1); ans=0; for (int i=2;i<=n;i++) if ((sa[i-1]<p&&sa[i]>p)||(sa[i-1]>p&&sa[i]<p)) ans=max(ans,height[i]); return ans; }}solver;
---
5 字符串hash
---
H(i)=s[i]+s[i+1]x+...s[n-2]x^(n-2-i)+s[n-1]x^(n-1-i)
Hash(i,L)=s[i]+s[i+1]x+...s[i+L-2]x^(L-2)+s[i+L-1]x^(L-1)
=H[i]-H[i+L]*x^L
对于LCP(i,j),二分答案L,判断Hash(i,L)与Hash(j,L)是否相等。
---
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>using namespace std;typedef unsigned long long ULL;const int SIZE = 100003;const int SEED = 13331;const int MAX_N = 50000 + 10;char s[MAX_N];struct HASH{ ULL H[MAX_N]; ULL XL[MAX_N]; int len; HASH(){} void build(char *s){ len=strlen(s); H[len]=0; XL[0]=1; for (int i=len-1;i>=0;i--){ H[i]=H[i+1]*SEED+s[i]; XL[len-i]=XL[len-i-1]*SEED; } } ULL hash(int i,int L){ return H[i]-H[i+L]*XL[L]; }}hs;
LCP
int lcp(int i,int j){ int l=0,r=min(len-i,len-j); int res=0; while (l<=r){ int mid=(l+r)/2; if (hash(i,mid)==hash(j,mid)){ res=mid; l=mid+1; } else{ r=mid-1; } } return res;}
---
6 后缀自动机
---
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <vector>#define sz(x) int(x.size())using namespace std;typedef vector<int> VI;const int maxn = 250000+10;class SuffixAutomaton{private: struct Node{ Node *suf, *go[26]; int val; Node(){ suf=NULL; val=0; memset(go,0,sizeof(go)); } void clear(){ suf=NULL; val=0; memset(go,0,sizeof(go)); } int calc(){ if (suf==0) return 0; return val-suf->val; } }; Node *root,*last; Node nodePool[maxn*2],*cur; Node* newNode(){ Node* res=cur++; res->clear(); return res; } int tot; void extend(int w){ Node *p=last; Node *np=newNode(); np->val=p->val+1; while (p&&!p->go[w]){ p->go[w]=np; p=p->suf; } if (!p){ np->suf=root; tot+=np->calc(); } else{ Node *q=p->go[w]; if (p->val+1==q->val){ np->suf=q; tot+=np->calc(); } else{ Node *nq=newNode(); memcpy(nq->go,q->go,sizeof(q->go)); tot-=p->calc()+q->calc(); nq->val=p->val+1; nq->suf=q->suf; q->suf=nq; np->suf=nq; tot+=p->calc()+q->calc()+np->calc()+nq->calc(); while (p&&p->go[w]==q){ p->go[w]=nq; p=p->suf; } } } last = np; }public: void init(){ cur=nodePool; root=newNode(); last=root; } VI getSubString(char s[]){ VI v; tot=0; int len=strlen(s); for (int i=0;i<len;i++){ extend(s[i]-'a'); v.push_back(tot); } return v; } int getLCS(char A[],char B[]){ int res=0,step=0; int lenA=strlen(A); int lenB=strlen(B); for (int i=0;i<lenA;i++) extend(A[i]-'a'); Node *p=root; for (int i=0;i<lenB;i++){ int x=B[i]-'a'; if (p->go[x]){ step++; p=p->go[x]; } else{ while (p&&!p->go[x]) p=p->suf; if (!p){ p=root; step=0; } else{ step=p->val+1; p=p->go[x]; } } res=max(res,step); } return res; }}atm;
---------------
五、几何
---
1 点·线
---
int dcmp(double x){ if (fabs(x)<EPS) return 0; return x>0?1:-1;}struct point{ double x,y; point(){} point(double _x,double _y):x(_x),y(_y){} /**运算操作**/ bool operator==(point a)const{ return dcmp(a.x-x)==0&&dcmp(a.y-y)==0; } bool operator<(point a)const{ return dcmp(x-a.x)==0?dcmp(y-a.y)<0:dcmp(x-a.x)<0; } friend point operator+(point a,point b){ return point(a.x+b.x,a.y+b.y); }//向量+向量=向量 friend point operator-(point a,point b){ return point(a.x-b.x,a.y-b.y); }//点-点=向量 friend point operator*(point a,double p){ return point(a.x*p,a.y*p); }//向量*数=向量 friend point operator/(point a,double p){ return point(a.x/p,a.y/p); }//向量/数=向量 /**基本信息计算**/ double len(){ return hypot(x,y); } double len2(){ return x*x+y*y; } double distance(point p){ return hypot(x-p.x,y-p.y); } /**向量变换**/ point rotate(double rad){ return point(x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad)); }//绕起点逆时针旋转rad point rotate(point p,double angle)//绕点p逆时针旋转angle角度 { point v=(*this)-p; double c=cos(angle),s=sin(angle); return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); } point rotleft(){ return point(-y,x); }//逆时针转90度 point rotright(){ return point(y,-x); }//顺时针转90度 point normal(){ double L=len(); return point(-y/L,x/L); }//单位法线即左转90度长度归一 point trunc(double r){ double l=len(); if (!dcmp(l)) return *this; r/=l; return point(x*r,y*r); }//长度变为r /**读入与输出**/ void input(){ scanf("%lf%lf",&x,&y); } void output(){ printf("%0.2f %0.2f\n",x,y); }};typedef point vect;double dot(point a,point b){ return a.x*b.x+a.y*b.y;}double cross(point a,point b){ return a.x*b.y-a.y*b.x;}double area3p(point a,point b,point c){ return cross(b-a,c-a)/2;}//三角形abc的面积double angle(vect a,vect b){ return acos(dot(a,b)/a.len()/b.len());}point GetLineIntersection(point P,vect v,point Q,vect w){ vect u=P-Q; double t=cross(w,u)/cross(v,w); return P+v*t;}//直线交点double ConvexPolygonArea(point *p,int n){ double area=0; for (int i=1;i<n-1;i++) area+=cross(p[i]-p[0],p[i+1]-p[0]); return area/2;}//多边形面积struct line{ point a,b; line(){} line(point _a,point _b){a=_a;b=_b;} line(point p,double angle){ a=p; if (dcmp(angle-PI/2)==0) b=a+point(0,1); else b=a+point(1,tan(angle)); }//倾斜角angle line (double _a,double _b,double _c){ if (dcmp(_a)==0){ a=point(0,-_c/_b); b=point(1,-_c/_b); }else if (dcmp(_b)==0){ a=point(-_c/_a,0); b=point(-_c/_a,1); }else{ a=point(0,-_c/_b); b=point(1,(-_c-_a)/_b); } }//ax+by+c=0 void adjust(){ if (b<a) swap(a,b); }//两点校准 /**运算操作**/ bool operator==(line v){ return (a==v.a)&&(b==v.b); } /**基本信息计算**/ double length(){ return a.distance(b); } double angle(){ double k=atan2(b.y-a.y,b.x-a.x); if (dcmp(k)<0) k+=PI; if (dcmp(k-PI)==0) k-=PI; return k; } /**线段相关**/ int relation(point p){ int c=dcmp(cross(p-a,b-a)); if (c<0) return 1;//点在逆时针 if (c>0) return 2;//点在顺时针 return 3;//平行 } bool pointonseg(point p){ return dcmp(cross(p-a,b-a))==0&&dcmp(cross(p-a,p-b))<=0; }//点p在线段上? bool parallel(line v){ return dcmp(cross(b-a,v.b-v.a))==0; }//与线段v平行? int segcrossseg(line v){ int d1=dcmp(cross(b-a,v.a-a)); int d2=dcmp(cross(b-a,v.b-a)); int d3=dcmp(cross(v.b-v.a,a-v.a)); int d4=dcmp(cross(v.b-v.a,b-v.a)); if ((d1^d2)==-2&&(d3^d4)==-2)return 2; return ((d1==0&&dcmp(dot(v.a-a,v.a-b)<=0))|| (d2==0&&dcmp(dot(v.b-a,v.b-b)<=0))|| (d3==0&&dcmp(dot(a-v.a,a-v.b)<=0))|| (d4==0&&dcmp(dot(b-v.a,b-v.b)<=0))); }//线段相交 0-不相交 1-非规范相交 2-规范相交 /**直线相关**/ int linecrosseg(line v){//直线v int d1=dcmp(cross(b-a,v.a-a)); int d2=dcmp(cross(b-a,v.b-a)); if ((d1^d2)==-2) return 2; return (d1==0||d2==0); }//0-平行 1-重合 2-相交 int linecrossline(line v){ if ((*this).parallel(v)) return v.relation(a)==3; return 2; }//0-平行 1-重合 2-相交 point crosspoint(line v){ double a1=cross(v.b-v.a,a-v.a); double a2=cross(v.b-v.a,b-v.a); return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1)); }//交点 double dispointtoline(point p){ return fabs(cross(p-a,b-a))/length(); }//点到线的距离 double dispointtoseg(point p){ if (dcmp(cross(p-b,a-b))<0||dcmp(cross(p-a,b-a))<0) return min(p.distance(a),p.distance(b)); return dispointtoline(p); } /**输入输出**/ void input(){ a.input(); b.input(); } void output(){ a.output(); b.output(); }};---
---------------
六、数学
---
2 数论基础
---
/*==============================================*\ | 最大公约数-辗转相除\*==============================================*/int gcd(int a,int b){ if (b==0) return a; return gcd(b,a%b);}/*==============================================*\ | 扩展欧几里得 | ax+by=gcd(a,b)\*==============================================*/int extgcd(int a,int b,int& x,int& y){ int d=a; if (b!=0){ d=extgcd(b,a%b,y,x); y-=(a/b)*x; }else{ x=1;y=0; } return d;}/*==============================================*\ | 素数-埃氏筛法\*==============================================*/int prime[maxn];bool is_prime[maxn+1];int sieve(int n){ int p=0; for (int i=0;i<=n;i++) is_prime[i]=true; is_prime[0]=is_prime[1]=false; for (int i=2;i<=n;i++){ if (is_prime[i]){ prime[p++]=i; for (int j=2*i;j<=n;j+=i) is_prime[j]=false; } } return p;}/*==============================================*\ | 快速幂\*==============================================*/LL modPow(LL x,LL n,LL mod){ if (n==0) return 1; LL res=modPow(x*x%mod,n/2,mod); if (n&1) res=res*x%mod; return res;}/*==============================================*\ | 高斯消元-列主元 | 求解Ax=b,A为矩阵 无解/多解时返回空数组\*==============================================*/const double eps=1e-8;typedef vector<double>vec;typedef vector<vec>mat;vec gaussJordan(const mat& A,const vec& b){ int n=A.size(); mat B(n,vec(n+1)); for (int i=0;i<n;i++) for (int j=0;j<n;j++) B[i][j]=A[i][j]; for (int i=0;i<n;i++) B[i][n]=b[i]; for (int i=0;i<n;i++){ int pivot=i; for (int j=i;j<n;j++){ if (abs(B[j][i])>abs(B[pivot][i])) pivot=j; } swap(B[i],B[pivot]); if (abs(B[i][i]<eps)) return vec();//无解或多解 for (int j=i+1;j<=n;j++) B[i][j]/=B[i][i]; for (int j=0;j<n;j++){ if (i!=j){ for (int k=i+1;k<=n;k++) B[j][k]-=B[j][i]*B[i][k]; } } } vec x(n); for (int i=0;i<n;i++) x[i]=B[i][n]; return x;}/*==============================================*\ | 逆元 | ax≡b(mod m) x=a逆×b | gcd(a,m)!=1逆元不存在\*==============================================*/int modInverse(int a,int m){ int x,y; extgcd(a,m,x,y); return (m+x%m)%m;}---
2 矩阵快速幂
---
/*==============================================*\ | 矩阵快速幂\*==============================================*/const int M=10000;typedef vector<int>vec;typedef vector<vec>mat;mat mul(mat &A,mat &B){ mat C(A.size(),vec(B[0].size())); for (int i=0;i<(int)A.size();i++){ for (int k=0;k<(int)B.size();k++){ for (int j=0;j<(int)B[0].size();j++){ C[i][j]=(C[i][j]+A[i][k]*B[k][j])%M; } } } return C;}mat pow(mat A,LL n){ mat B(A.size(),vec(A.size())); for (int i=0;i<(int)A.size();i++){ B[i][i]=1; } while (n>0){ if (n&1) B=mul(B,A); A=mul(A,A); n>>=1; } return B;}
---------------
七、其他
---
1 哈希Hash
---
1.1 普通hash
#include <iostream>#include <cstring>using namespace std;const int maxn=11111;const int maxh=10000019;int head[maxh];int next[maxh];long long st[maxn];void hash_init(){ memset(head,0,sizeof(head));}int hash(long long p,int prime=10000019){ int h; //hash操作 h=p%prime; return h;}bool add_hash(int s){ int h=hash(st[s]); int u=head[h]; while(u){ //if (memcmp(st[u],st[s],sizeof(st[s]))==0) return 0; //if (strcmp(st[u],st[s])==0) return 0; if (st[u]==st[s]) return 0; u=next[u]; } next[s]=head[h]; head[h]=s; return 1;}bool search_hash(long long p){ int h=hash(p); int u=head[h]; while (u){ //if (memcmp(st[u],p,sizeof(st[u]))==0) return 1; //if (strcmp(st[u],str)==0) return 1; if (st[u]==p) return 1; u=next[u]; } return 0;}
---
1.2 树hash
---
从某个常数开始,每次乘以 p,和一个元素异或,再除以 q 取余,再乘以 p,和下一个元素异或,除以 q 取余.....
一直进行到最后一个元素为止。最后把所得到的结果乘以 b,再对 q 取余。
---
hash[u]=977872; for(i=0;i<son[u];i++) { for(j=i;j<son[u]&&q[i].hash==q[j].hash;j++) { hash[u]*=P; hash[u]^=q[j].hash; hash[u]%=mod; } j--; ans[u]*=cal(q[i].ans+j-i,j-i+1); ans[u]%=mod; i=j; }
---
2 各种最长子序列
---
void LXS(int* a,int* f,int n){ vector<int>d; int l,r; REP(i,n) { //l=lower_bound(d.begin(),d.end(),a[i])-d.begin(); r=upper_bound(d.begin(),d.end(),a[i])-d.begin(); if (r==sz(d)) d.push_back(a[i]); else d[r]=a[i]; f[i]=r+1; }}
---------------
---------------
---------------
---------------
- 【Code Library】不超过25个页面的材料
- 搞了个code library玩玩
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- Android的材料设计兼容库(Design Support Library)
- 限制editext输入的字符数不超过140个字符
- Xcode的快捷方式(Code Snippet Library)
- 【强烈推荐】29个材料方面的数据库网址(更全面!!!)
- 【强烈推荐】29个材料方面的数据库网址(更全面!!!)
- 那位朋友提供个C#的学习材料!
- Android之多媒体--使用VideoView播放视频
- ARM分类
- Linux线程-互斥锁pthread_mutex_t
- 最大流算法总结
- C++对象语义与值语义
- 【Code Library】不超过25个页面的材料
- word下不能使用搜狗输入法
- Android之多媒体--使用MediaPlayer和SurfaceView播放视频
- StringUtils. indexOf 用法
- JSP向Servlet传中文
- tomcat修改启动内存
- 背包问题解析
- 概率(3)一根木棍折断成3段构成一个三角形的概率
- oracle10g goldengate安装oracle-oracle单向复制