ACM常用模板--图,字符串,数据处理

#图论

#1 - 费用流

struct E {
	int to,flow,cast,next;
	E(int to=0,int flow=0,int cast=0,int next=0):
		to(to),flow(flow),cast(cast),next(next){}
}g[N*N];

int fr[N],tot=1; // !!

void Add(int from,int to,int flow,int cast) {
//cout<<"E"<<from<<" "<<to<<" "<<flow<<" "<<cast<<"\n"; 
	g[++tot] = E(to,flow,cast,fr[from]);
	fr[from]  = tot;
	g[++tot] = E(from,0,-cast,fr[to]);
	fr[to]  = tot;
}

int d[N],fl[N],p[N],inq[N],st,ed,Cast,n,m;  

bool spfa() {
	static int idd = 0; ++idd;
	memset(d,127/3,sizeof(d[0])*(ed+6));
	queue<int> q;
	q.push(st); d[st] = 0; inq[st] = idd; fl[st] = 1e9;
	while(q.size()) {
		int t = q.front(); q.pop(); inq[t] = 0; 
		for (int i = fr[t]; i; i = g[i].next) {
			int to = g[i].to;
			if(d[to] > d[t]+g[i].cast && g[i].flow) {
				d[to] = d[t]+g[i].cast;
				fl[to] = min(fl[t],g[i].flow);
				p[to] = i;
				if(inq[to] != idd) {
					inq[to] = idd;
					q.push(to);
				}
			}
		}
	}
	return d[ed] != d[ed+1];
}

void mcmf() {
	Cast += fl[ed]*d[ed];
	for(int t = ed,e = p[t]; t != st; ) {
		g[e].flow -= fl[ed];
		g[e^1].flow += fl[ed];
		t = g[e^1].to;
		e = p[t];
	}
}

#2 - 最大流


bool bfs() {
    memset(d,-1,sizeof(d[0])*(ed+10));
	queue<int> q;
	q.push(st); d[st] = 0;
	while(q.size()) {
		int t = q.front(); q.pop();
		for (int i = fr[t]; i; i = g[i].next) {
			int to = g[i].to;
			if(d[to] == -1 && g[i].flow) {
				d[to] = d[t]+1;
				q.push(to);
			}
		}
	}
	return d[ed] != -1;
}

int dfs(int t,int mf) {
	if(t == ed || mf == 0) return mf;
	int tmp = 0;
	for (int &i = cur[t]; i&&mf; i = g[i].next) {
		if(g[i].flow == 0 || d[g[i].to] != d[t]+1) continue;
		int f = dfs(g[i].to,min(mf,g[i].flow));
		mf -= f; tmp += f;
		g[i].flow -= f; g[i^1].flow += f;
	}
	if(!tmp) d[t] = -1;
	return tmp;
}

int Dinic(int s,int t) {
	st = s; ed = t;int max_flow = 0;
	while(bfs()) {
      copy(fr,fr+ed+2,cur);
	  max_flow += dfs(st,inf);
	}
	return max_flow;
}

#3 - tarjan强连通分量

void tarjan(int x) {
	dfn[x] = low[x] = ++id;
	stack[++top] = x; 
	ins[x] = true;
	for (int i = fr[x]; i; i = g[i].next) {
		if(dfn[g[i].to] == -1) {
			tarjan(g[i].to);
			low[x] = min(low[x],low[g[i].to]);
		} else if(ins[g[i].to])
		   low[x] = min(low[x],dfn[g[i].to]);
	}
	if(low[x] == dfn[x]) {
		cnt++;
		while(stack[top] != x) {
			f[stack[top]] = cnt;
			ins[stack[top]] = false;
			top--;
		}
		ins[x] = false;
		f[stack[top--]] = cnt;
	}
}

#4-*2-sat

void Add(int ta,int a,int tb,int b) {
	a = a<<1|ta; b = b<<1|tb;
	g[a^1].push_back(b);
	g[b^1].push_back(a);
}

bool Mark[N];int st[N],top,n,m,k;

bool dfs(int t) {
	if(Mark[t]) return 1;
	if(Mark[t^1]) return 0;
	Mark[st[++top] = t] = true;
	for (int i = 0; i < g[t].size(); i++)
	  if(!dfs(g[t][i])) return false;
	return true; 
}

bool pd() {
	for (int i = 2; i <= n*2; i+=2,top = 0) 
	 if(!Mark[i] && !Mark[i^1]) {
		 if(!dfs(i)) {
		    for( ; top; Mark[st[top--]] = 0);
		    if(!dfs(i^1)) return false;	
	 	 }
	 }
	return true; 
}

#5 *k-short

struct No{
	int t,dis;No(int t,int dis):t(t),dis(dis){}
	bool operator < (const No &lhs) const {return dis+d[t] > lhs.dis+d[lhs.t];}
};
 
int cnt[N];
priority_queue<No> q1;
void Astar(int st,int ed,int k) {
	init();
	q1.push(No(st,0));
	while(q1.size()) {
		No t = q1.top();q1.pop();
		if(t.t == ed) {k--;if(k==0) return;}
		for (int i = fr[t.t]; i; i = g[i].next)
		  q1.push(No(g[i].to,t.dis+g[i].w));
	}
    while(k--) printf("-1\n");
}

字符串

#1 - kmp

// cin >> s+1;
void getfail() {
    int j = 0; f[1] = 0;
    for (int i = 2; i <= len1; i++) {
        while(j && s1[j+1] != s1[i]) j = f[j];
        if(s1[j+1] == s1[i]) j++;
        f[i] = j;
    }
}

void kmp() {
    int j = 0;
    for (int i = 1; i <= len2; i++) {
        while(j && s1[j+1] != s2[i]) j = f[j];
        if(s1[j+1] == s2[i]) j++;
        if(j == len1) { j = f[j]; tot++;}
    }
} 

#2 - trie树&AC自动机

struct Trie {int Next[2];bool End;}a[N];
int Fail[N];
int tot = 0,ans;
 
void Ins(char *s) {
	int len = strlen(s),now = 0;
	for (int i = 0; i < len; i++) {
		int c = s[i]-'0';
		if(!a[now].Next[c]) a[now].Next[c] = ++tot;
		now = a[now].Next[c];
	}
	a[now].End = true;
} 
 
void Get_fail() {
	static queue<int> q;
	for (int i = 0; i < 2; i++) 
	 if(a[0].Next[i]) q.push(a[0].Next[i]);
	while(q.size()) {
		int t = q.front(); q.pop();
		a[t].End |= a[Fail[t]].End;
		for (int i = 0; i < 2; i++) {
			if(!a[t].Next[i]) {a[t].Next[i] = a[Fail[t]].Next[i];continue;}
			Fail[a[t].Next[i]] = a[Fail[t]].Next[i];
			q.push(a[t].Next[i]);
		}
	}
}


#3 - 后缀数组


void radix(int *s,int *a,int *b,int n,int m) {
	static int c[N];
	memset(c,0,sizeof(c[0])*(m+2));
	for (int i = n-1; i >= 0; --i) ++c[s[a[i]]];
	for (int i = 1; i <= m; ++i) c[i] += c[i-1];
	for (int i = n-1; i >= 0; --i) b[--c[s[a[i]]]] = a[i]; // rank 0 - n-1
}

void suffix(int *s,int *sa,int *rk,int n,int m) {
	static int a[N],b[N];
	for (int i = 0; i < n; ++i) a[i] = i;
	radix(s,a,sa,n,m);
	rk[sa[0]] = 0;
	for (int i = 1; i < n; ++i)
	  rk[sa[i]] = rk[sa[i-1]]+(s[sa[i-1]]==s[sa[i]]?0:1);
	for (int i = 0; 1<<i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			sa[j] = j;
			a[j] = rk[j]+1;
			b[j] = j+(1<<i)>=n?0:rk[j+(1<<i)]+1;
		}
		radix(b,sa,rk,n,n); radix(a,rk,sa,n,n);
		rk[sa[0]] = 0;
		for (int j = 1; j < n; ++j)
		 rk[sa[j]] = rk[sa[j-1]]+(a[sa[j]]==a[sa[j-1]]&&b[sa[j]]==b[sa[j-1]]?0:1);
		if(rk[sa[n-1]] == n-1) break;
	}
}

void calcht(int *s,int *sa,int *rk,int *h,int n) {
	int k = 0; h[0] = 0;
	for (int i = 0; i < n; ++i) {
		if(k) --k;
		if(rk[i]) {
			while(s[i+k] == s[sa[rk[i]-1]+k]) ++k;
			h[rk[i]] = k;
		}
	}
}

#4 - *回文树

int last,m,tot,sum,slen;
char S[MAXX];
int cnt[MAXX],fail[MAXX],len[MAXX],next[MAXX][26];
 //next 小心CE
void init() {
	S[0] = '#';
	fread(S+1,1,MAXX-10,stdin);
    slen = strlen(S+1);
    len[0] = 0; len[1] = -1;
    tot = 1;last = 0;
	fail[0] = 1;
}
int getfail(int x) {
	while(S[sum] != S[sum-len[x]-1])
	   x = fail[x];
	return x;
}
void add(char c) {
	c -= 'a';
	int cur = getfail(last);
	if(!next[cur][c]) {
		len[++tot] = len[cur]+2;
		fail[tot] = next[getfail(fail[cur])][c];
		next[cur][c] = tot;
	}
	last = next[cur][c]; 
	cnt[last]++;
}
inline void work() {
	init();
	for (sum = 1; sum <= slen; sum++) add(S[sum]);
	for(int i = tot; i >= 2; i--) cnt[fail[i]] += cnt[i];
}

#数据结构

#1-fhq treap


#define lh(o)  t[o].lch
#define rh(o)  t[o].rch
#define L      t[o].lch
#define R      t[o].rch
#define MP     make_pair
typedef pair<int,int> pii;

struct Node {
   int lch,rch,siz,r,id;
   LL v,lazy;
}t[N];
int tot = 1,pool[N],top;

inline int New_Node(LL v,int id) {
	int o = top ? pool[top--]:++tot;
    t[o].sum = t[o].v = v; t[o].r = rand(); t[o].siz = 1; 
    t[o].lch = t[o].rch = 0;  t[o].lazy = 0; t[o].id = id;
	return o;
}

inline void up(int o) {
   t[o].siz = t[L].siz+t[R].siz+1;
}

int mer(int a,int b) {
	return !a||!b ? a^b : t[a].r<t[b].r ?
	(down(a),rh(a) = mer(rh(a),b),up(a),a):
	(down(b),lh(b) = mer(a,lh(b)),up(b),b);
}

inline void get(int &x,int &y,const pii tp) {x=tp.first;y=tp.second;}
pii spl(int o,int k) {
	if(!o) return MP(0,0);  down(o);
	int p = k-t[L].siz-1; return p>=0 ?
	(get(R,p,spl(R,p)),up(o),MP(o,p)):
	(get(p,L,spl(L,k)),up(o),MP(p,o));
}

#2 - *可并堆

struct Node {
	int lch,rch,val,tot;
	Node(){}Node(int C):val(C),lch(0),rch(0),tot(1){}
}t[N];
 
void up(int o) {
	t[o].tot = t[t[o].lch].tot+t[t[o].rch].tot+1;
}
 
int Mer(int a,int b) {
	if(!a||!b) return a^b;
	if(t[a].val>t[b].val) {
	   t[a].lch = Mer(t[a].lch,b);
	   swap(t[a].lch,t[a].rch); 
	   return up(a),a;
	} else {
	   t[b].lch = Mer(t[b].lch,a);
	   swap(t[b].lch,t[b].rch); 
	   return up(b),b;
	}
}
 
void Pop(int &o) {o = Mer(t[o].lch,t[o].rch);}

#3-*kd_tree

struct Node {
	int d[2],ma[2],mi[2],l,r;LL sum,v;
	Node(int x=0,int y=0,LL v=0):v(v){sum=v;d[0]=x,d[1]=y;ma[0]=ma[1]=-inf;mi[0]=mi[1]=inf;l=r=sum=0;}
}t[N];
int D,n,m,rt,now,tot;
int xx,yy,x,y;
LL ans;
 
bool operator < (const Node &a,const Node &b) {return a.d[D] < b.d[D];}
 
#define L t[o].l
#define R t[o].r
 
inline void up(int o) {
	for (int i = 0; i < 2; i++) {
		t[o].ma[i] = max(t[o].d[i],max(t[L].ma[i],t[R].ma[i]));
		t[o].mi[i] = min(t[o].d[i],min(t[L].mi[i],t[R].mi[i]));
	}
	t[o].sum = t[L].sum+t[R].sum+t[o].v;
}
 
void build(int l,int r,int &o,int cas) {
	if(l>r) return;  D = cas;
	int &mid = o; mid = (l+r)>>1;
	nth_element(t+l,t+mid,t+r+1);
	build(l,mid-1,L,cas^1); build(mid+1,r,R,cas^1);
	up(o);
}
 
LL query(int o) {
    if(!o) return;
	if(o != now) downval(ans,dis(o,now));
	int miL = Best(L),miR = Best(R);
	if(miL < miR) {
		if(miL < ans) query(L);
		if(miR < ans) query(R);
	} else {
		if(miR < ans) query(R);
		if(miL < ans) query(L);
	}
}
 
void modify(int &o,int cas) {
	if(!o) {t[o=++tot] = t[now];up(o);return;}
	D = cas;
	if(t[now] < t[o]) modify(L,cas^1);
	else modify(R,cas^1);
	up(o);
}

#4-线段树

//1
void build(int l,int r,int &o) {
	t[o = ++tot].l = l; t[o].r = r;
	if(l == r) {read(t[o].maxv);return;}
	int mid = (l+r) >> 1;
	build(l,mid,t[o].lt); build(mid+1,r,t[o].rt);
	t[o].maxv = max(t[t[o].lt].maxv,t[t[o].rt].maxv);
}
 
int query(int l,int r,int o) {
	if(!o) return 0;
	if(l <= t[o].l && t[o].r <= r) return t[o].maxv;
	int mid = (t[o].l+t[o].r) >> 1,tmp = 0;
	if(l <= mid) tmp = query(l,r,t[o].lt);
    if(r > mid) tmp = max(tmp,query(l,r,t[o].rt));
	return tmp;
}
//2
void build() {
	for (M=1; M<=n+1; M<<=1);
	for (int i = M+1; i <= M+n; i++) read(sum[i]);
	for (int i = M-1; i; i--) push_up(i); 
}
 
void add(int x,int v) {
	sum[M+x] += v;while(x) push_up(x>>=1); 
}
 
int Sum(int x,int y,int ans = 0) {
	for (x=x+M-1,y=y+M+1;x^y^1;x>>=1,y>>=1) {
		if(~x&1) ans += sum[x^1];
		if(y&1) ans += sum[y^1];
	} return ans;
} 

#5 - *二维树状数组

 void Add(int x,int y,int v) {
	 for (int i = x; i <= r; i+=lb(i))
	  for (int j = y; j <= c; j+=lb(j))
	   S[i][j] += v;
   }
 
   int Sum(int x,int y) {
	 int tmp = 0;
	 for (int i = x; i >= 1; i-=lb(i))
	  for (int j = y; j >= 1; j-=lb(j))
	   tmp += S[i][j];
	 return tmp;
   }

#6 - 点分

void getrt(int t,int fa) {
	siz[t] = 1; mx[t] = 0;  // bug
	for (int i = fr[t]; i; i = g[i].next) {
		int to = g[i].to;
		if(to == fa || vis[to]) continue;
		getrt(to,t);
		siz[t] += siz[to];
		upval(mx[t],siz[to]);
	} 
	upval(mx[t],Size-siz[t]);
	if(mx[t] < mx[rt]) rt = t;
}
 
int k,ans = inf;
void calc(int t) {}

void slove(int t) {
	calc(t); 
	vis[t] = 1;
	for (int i = fr[t]; i; i = g[i].next) {
		int to = g[i].to;
		if(vis[to]) continue;
		//ans -= calc(to);
		rt = 0; Size = siz[to]; getrt(to,-1);
		slove(rt);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值