Hihocoder KMP
#include<bits/stdc++.h>
#define reg register
const int maxn = 1000005;
char s[maxn], T[maxn];
int len_s, len_t, cnt, N;
int nxt[maxn];
void Getnxt(){
nxt[0] = -1;
int i = 0, t = -1;
while(i < len_s)
if(t == -1 || s[i] == s[t]) nxt[++ i] = ++ t; // "==" --> "!="
else t = nxt[t];
}
void KMP(){
int t1 = 0, t2 = 0;
while(t2 < len_t)
if(t1 == -1 || s[t1] == t[t2]){
t1 ++, t2 ++;
if(t1 == len_s){
t1 = nxt[t1];
cnt ++;
}
}else t1 = nxt[t1];
}
void Work(){
scanf("%s%s", s, T);
len_s = strlen(s), len_t = strlen(T);
Getnxt();
cnt = 0;
KMP();
printf("%d\n", cnt);
}
int main(){
scanf("%d", &N);
while(N --) Work();
return 0;
}
Hihocoder #1077 : RMQ问题再临-线段树 线段树单点修改, 区间最小值
#include<bits/stdc++.h>
#define reg register
const int maxn = 1e6 + 10;
int N, M;
int Ql, Qr;
struct Node{
int v, l, r, min_v;
} T[maxn<<2];
void Build(int k, int l, int r){
T[k].l = l, T[k].r = r;
if(l == r){
scanf("%d", &T[k].v), T[k].min_v = T[k].v;
return ;
}
int mid = l+r >> 1;
Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
T[k].min_v = std::min(T[k<<1].min_v, T[k<<1|1].min_v);
}
int Query(int k){
int l = T[k].l, r = T[k].r;
if(Ql <= l && r <= Qr) return T[k].min_v;
int mid = l+r >> 1;
if(mid < Ql) return Query(k<<1|1);
else if(mid >= Qr) return Query(k<<1);
return std::min(Query(k<<1|1), Query(k<<1));
}
void Modify(int k){
int l = T[k].l, r = T[k].r;
if(l == r){
T[k].min_v = T[k].v = Qr;
return ;
}
int mid = l+r >> 1;
if(Ql <= mid) Modify(k<<1);
else Modify(k<<1|1);
T[k].min_v = std::min(T[k<<1].min_v, T[k<<1|1].min_v);
}
int main(){
scanf("%d", &N);
Build(1, 1, N);
scanf("%d", &M);
int opt;
while(M --){
scanf("%d%d%d", &opt, &Ql, &Qr);
if(!opt){
int Ans = Query(1);
printf("%d\n", Ans);
}
else Modify(1);
}
return 0;
}
P3372 【模板】线段树 1线段树区间修改, 区间和
注意标记的加值
#include<bits/stdc++.h>
#define reg register
const int maxn = 1e6 + 10;
typedef long long ll;
int N, M;
int Ql, Qr;
ll Qv;
int tag[maxn<<2];
struct Node{
ll v, min_v, sum;
int l, r;
} T[maxn<<2];
void Build(int k, int l, int r){
T[k].l = l, T[k].r = r;
if(l == r){
scanf("%lld", &T[k].v), T[k].min_v = T[k].v, T[k].sum = T[k].v;
return ;
}
int mid = l+r >> 1;
Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
T[k].min_v = std::min(T[k<<1].min_v, T[k<<1|1].min_v);
T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
}
void Push_down(int k){
int l, r;
tag[k<<1] += tag[k], tag[k<<1|1] += tag[k];
l = T[k<<1].l, r = T[k<<1].r;
T[k<<1].sum += 1ll*(r - l + 1) * tag[k];
l = T[k<<1|1].l, r = T[k<<1|1].r;
T[k<<1|1].sum += 1ll*(r - l + 1) * tag[k];
tag[k] = 0;
}
void Modify_2(int k){
int l = T[k].l, r = T[k].r;
if(Ql <= l && r <= Qr){
T[k].sum += 1ll*(r-l+1)*Qv;
tag[k] += Qv;
return ;
}
if(tag[k]) Push_down(k);
int mid = l+r >> 1;
if(mid < Ql) Modify_2(k<<1|1);
else if(mid >= Qr) Modify_2(k<<1);
else Modify_2(k<<1), Modify_2(k<<1|1);
T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
}
ll Query_2(int k){
int l = T[k].l, r = T[k].r;
if(Ql <= l && r <= Qr) return T[k].sum;
if(tag[k]) Push_down(k);
ll tmp = 0;
int mid = l+r >> 1;
if(mid < Ql) tmp += Query_2(k<<1|1);
else if(mid >= Qr) tmp += Query_2(k<<1);
else tmp += Query_2(k<<1) + Query_2(k<<1|1);
T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
return tmp;
}
int main(){
scanf("%d%d", &N, &M);
Build(1, 1, N);
int opt;
while(M --){
scanf("%d%d%d", &opt, &Ql, &Qr);
if(opt == 1){
scanf("%lld", &Qv);
Modify_2(1);
}else{
ll Ans = Query_2(1);
printf("%lld\n", Ans);
}
}
return 0;
}
树链剖分
注意Dfn序和原编号的区别
#include<bits/stdc++.h>
#define reg register
const int maxn = 1e5+10;
int N, M, R, P;
int head[maxn], size[maxn], max_son[maxn], max_w[maxn];
int top[maxn], dfn[maxn], Fa[maxn], dep[maxn], w[maxn], max_num[maxn];
int tim, num0;
namespace Seg{
struct Node{
int v, l, r, tag;
} T[maxn<<2];
void Build(int k, int l, int r){
T[k].l = l, T[k].r = r;
if(l == r){
T[k].v = T[k].tag = 0;
return ;
}
int mid = l+r >> 1;
Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
T[k].v = (1ll*T[k<<1].v + T[k<<1|1].v) % P;
}
void Push_down(int k){
T[k<<1].tag = (1ll*T[k<<1].tag + T[k].tag) % P;
T[k<<1|1].tag = (1ll*T[k<<1|1].tag + T[k].tag) % P;
int l, r;
l = T[k<<1].l, r = T[k<<1].r;
T[k<<1].v = (1ll*T[k<<1].v + (1ll*T[k].tag*(r - l + 1) % P)) % P;
l = T[k<<1|1].l, r = T[k<<1|1].r;
T[k<<1|1].v = (1ll*T[k<<1|1].v + (1ll*T[k].tag*(r - l + 1) % P)) % P;
T[k].tag = 0;
}
void Modify(int k, const int &Ql, const int &Qr, const int &v){
int l = T[k].l, r = T[k].r;
if(Ql <= l && r <= Qr){
T[k].v += 1ll*v*(r - l + 1) % P;
T[k].tag = (1ll*T[k].tag + v) % P;
return ;
}
if(T[k].tag) Push_down(k);
int mid = l+r >> 1;
if(mid < Ql) Modify(k<<1|1, Ql, Qr, v);
else if(mid >= Qr) Modify(k<<1, Ql, Qr, v);
else Modify(k<<1, Ql, Qr, v), Modify(k<<1|1, Ql, Qr, v);
T[k].v = (1ll*T[k<<1].v + T[k<<1|1].v) % P;
}
int Query(int k, const int &Ql, const int &Qr){
int l = T[k].l, r = T[k].r;
if(Ql <= l && r <= Qr) return T[k].v;
if(T[k].tag) Push_down(k);
int mid = l+r >> 1;
T[k].v = (1ll*T[k<<1].v + T[k<<1|1].v) % P;
if(mid < Ql) return Query(k<<1|1, Ql, Qr);
else if(mid >= Qr) return Query(k<<1, Ql, Qr);
return (1ll*Query(k<<1|1, Ql, Qr) + Query(k<<1, Ql, Qr)) % P;
}
}
struct Edge{ int nxt, to; } edge[maxn<<1];
void Add(int from, int to){
edge[++ num0] = (Edge){ head[from], to };
head[from] = num0;
}
void DFS_1(int k, int fa){
size[k] = 1;
max_son[k] = 0, max_w[k] = 0;
dep[k] = dep[fa] + 1;
Fa[k] = fa;
for(reg int i = head[k]; i; i = edge[i].nxt){
int to = edge[i].to;
if(to == fa) continue ;
DFS_1(to, k);
size[k] += size[to];
if(size[to] > max_w[k]){
max_w[k] = size[to];
max_son[k] = to;
}
}
}
void DFS_2(int k, int fa){
dfn[k] = ++ tim;
Seg::Modify(1, dfn[k], dfn[k], w[k]);
top[k] = fa;
if(max_son[k]) DFS_2(max_son[k], fa);
for(reg int i = head[k]; i; i = edge[i].nxt){
int to = edge[i].to;
if(dfn[to]) continue ;
DFS_2(to, to);
}
max_num[k] = tim;
}
void Modify_P(int x, int y, int z){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) std::swap(x, y);
Seg::Modify(1, dfn[top[x]], dfn[x], z);
x = Fa[top[x]];
}
if(dfn[x] > dfn[y]) std::swap(x, y);
Seg::Modify(1, dfn[x], dfn[y], z);
}
int Query_P(int x, int y){
int res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) std::swap(x, y);
res = (1ll*res+Seg::Query(1, dfn[top[x]], dfn[x])) % P;
x = Fa[top[x]];
}
if(dfn[x] > dfn[y]) std::swap(x, y);
res = (1l*res + Seg::Query(1, dfn[x], dfn[y])) % P;
return res;
}
void Work(){
int opt, x, y, z;
scanf("%d", &opt);
if(opt == 1){
scanf("%d%d%d", &x, &y, &z);
Modify_P(x, y, z);
}else if(opt == 2){
scanf("%d%d", &x, &y);
int Ans = Query_P(x, y);
printf("%d\n", Ans);
}else if(opt == 3){
scanf("%d%d", &x, &z);
Seg::Modify(1, dfn[x], max_num[x], z);
}else{
scanf("%d", &x);
int Ans = Seg::Query(1, dfn[x], max_num[x]);
printf("%d\n", Ans);
}
}
int main(){
scanf("%d%d%d%d", &N, &M, &R, &P);
int a, b;
for(reg int i = 1; i <= N; i ++) scanf("%d", &w[i]);
Seg::Build(1, 1, N);
for(reg int i = 1; i < N; i ++){
scanf("%d%d", &a, &b);
Add(a, b), Add(b, a);
}
DFS_1(R, R); // second 'R' --> '0'
DFS_2(R, R); // second 'R' --> '0'
while(M --) Work();
return 0;
}
普通平衡树
> 和 < 的区别
5个数组
对一个节点进行操作后进行Splay
前驱后继的操作注意特判 ↓ ↓ ↓
int S_pre(int x, short opt){ // 1: su 0: pre
find(x);
if(opt == 1){ //特判
if(key[rot] > x) return rot;
}else if(key[rot] < x) return rot;
int t = ch[rot][opt]; opt ^= 1;
while(ch[t][opt]) t = ch[t][opt];
return t;
}
插入的时候必须Splay
注意赋值关系 ↓ ↓ ↓
//AC
int Kth(int t, int x){
while(1){
if(ch[t][0] && size[ch[t][0]] >= x) t = ch[t][0];
else if(size[ch[t][0]] + cnt[t] < x) x -= size[ch[t][0]] + cnt[t], t = ch[t][1];
else return t;
}
}
//WA
int Kth(int t, int x){
while(1){
if(ch[t][0] && size[ch[t][0]] >= x) t = ch[t][0];
else if(size[ch[t][0]] + cnt[t] < x) t = ch[t][1], x -= size[ch[t][0]] + cnt[t];
else return t;
}
}
#include<bits/stdc++.h>
#define reg register
const int maxn = 100005;
int num0, rot;
int cnt[maxn], size[maxn];
int par[maxn], ch[maxn][2], key[maxn];
inline void Push_up(int x){ size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x]; }
inline bool chk(int x){ return ch[par[x]][1] == x; }
void rotate(int x){
int y = par[x], z = par[y], d = chk(x), s = ch[x][d^1];
ch[y][d] = s, par[s] = y;
ch[z][chk(y)] = x, par[x] = z;
ch[x][d^1] = y, par[y] = x;
Push_up(y), Push_up(x);
}
void Splay(int x, int aim=0){
while(par[x] != aim){
int y = par[x], z = par[y];
if(z != aim){
if(chk(x) == chk(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(!aim) rot = x;
}
void Insert(int x){ //~~
int t = rot, last = 0;
while(t && key[t] != x){
last = t;
t = ch[t][key[t] < x];
}
if(t) cnt[t] ++;
else{
key[t = ++ num0] = x;
if(last) ch[last][key[last] < x] = num0;
ch[num0][0] = ch[num0][1] = 0, size[num0] = 1;
par[num0] = last;
cnt[num0] = 1;
}
Splay(t);
}
void find(int x){
if(!rot) return ;
int t = rot;
while(ch[t][key[t] < x] && key[t] != x) t = ch[t][key[t] < x];
Splay(t);
}
int S_pre(int x, short opt){ // 1: su 0: pre
find(x);
if(opt == 1){
if(key[rot] > x) return rot;
}else if(key[rot] < x) return rot;
int t = ch[rot][opt]; opt ^= 1;
while(ch[t][opt]) t = ch[t][opt];
return t;
}
void Remove(int x){
int su = S_pre(x, 1), pre = S_pre(x, 0);
Splay(pre), Splay(su, pre);
int t = ch[su][0];
if(cnt[t] == 1) ch[su][0] = 0;
else cnt[t] --, Splay(t); //~~
}
inline void Ask_1(int x){
find(x);
printf("%d\n", size[ch[rot][0]]);
}
int Kth(int t, int x){
while(1){
if(ch[t][0] && size[ch[t][0]] >= x) t = ch[t][0];
else if(size[ch[t][0]] + cnt[t] < x) x -= size[ch[t][0]] + cnt[t], t = ch[t][1];
else return t;
}
}
inline void Ask_2(int x){
// printf("fuck: %d size: %d cnt %d\n",rot, size[ch[rot][0]], cnt[rot]);
int t = Kth(rot, x);
printf("%d\n", key[t]);
}
void Work(){
int opt, x;
scanf("%d%d", &opt, &x);
if(opt == 1) Insert(x);
else if(opt == 2) Remove(x);
else if(opt == 3) Ask_1(x);
else if(opt == 4) Ask_2(x+1);
else if(opt == 5) printf("%d\n", key[S_pre(x, 0)]);
else printf("%d\n", key[S_pre(x, 1)]);
}
int main(){
int N;
scanf("%d", &N);
Insert(0xcfcfcfcf), Insert(0x3f3f3f3f);
for(reg int i = 1; i <= N; i ++) Work();
return 0;
}
最大流
#include<bits/stdc++.h>
#define reg register
const int maxn = 100005;
const int inf = 0x7f7f7f7f;
int N, M, S, T, num0;
int head[maxn], cur[maxn], dep[maxn];
struct Edge{
int nxt, to, dis, flow;
} edge[maxn<<1];
void Add(int from, int to, int Dis){
edge[num0] = (Edge){ head[from], to, Dis, 0 };
head[from] = num0 ++;
}
bool BFS(){
memset(dep, -1, sizeof dep);
for(reg int i = 0; i <= N; i ++) cur[i] = head[i];
dep[S] = 1;
std::queue <int> Q;
Q.push(S);
while(!Q.empty()){
int t = Q.front(); Q.pop();
for(reg int i = head[t]; ~i; i = edge[i].nxt){
int to = edge[i].to;
if(dep[to] == -1 && edge[i].dis > edge[i].flow){
dep[to] = dep[t] + 1;
Q.push(to);
}
}
}
return dep[T] != -1;
}
int DFS(int k, int W){
if(k == T) return W;
for(reg int &i = cur[k]; ~i; i = edge[i].nxt){
int to = edge[i].to;
if(dep[to] == dep[k] + 1 && edge[i].dis > edge[i].flow){
int tmp = DFS(to, std::min(W, edge[i].dis - edge[i].flow));
if(tmp){
edge[i].flow += tmp;
edge[i^1].flow -= tmp;
return tmp;
}
}
}
return 0;
}
int Dinic(){
int Ans = 0;
while(BFS()){
while(int res = DFS(S, inf)) Ans += res;
}
return Ans;
}
int main(){
scanf("%d%d%d%d", &N, &M, &S, &T);
int x, y, z;
memset(head, -1, sizeof head);
for(reg int i = 1; i <= M; i ++){
scanf("%d%d%d", &x, &y, &z);
Add(x, y, z), Add(y, x, 0);
}
printf("%d\n", Dinic());
return 0;
}
/*
memset(head, -1, sizeof head)
void Add(int from, int to, int Dis){
edge[num0] = (Edge){ head[from], to, Dis, 0 };
head[from] = num0 ++;
}
*/
最小费用最大流
#include<bits/stdc++.h>
#define reg register
const int maxn = 50005;
int N, M, S, T, num0;
int head[maxn];
std::bitset <5005> Used;
int Dis[5005], Flow[5005], Pre[5005], Pre_1[5005];
struct Edge{
int nxt, to, dis, flow, cost;
} edge[maxn << 1];
void Add(int from, int to, int dis, int cost){
edge[num0] = (Edge){ head[from], to, dis, 0, cost };
head[from] = num0 ++;
}
int Spfa(){
memset(Dis, 0x3f, sizeof Dis);
memset(Flow, 0x3f, sizeof Flow);
Used.reset();
std::queue <int> Q;
Q.push(S), Dis[S] = 0, Used.set(S, 1);
while(!Q.empty()){
int t = Q.front(); Q.pop();
//printf("fuck %d\n", t);
Used.set(t, 0);
for(reg int i = head[t]; ~i; i = edge[i].nxt){
int to = edge[i].to;
if(Dis[to] > Dis[t] + edge[i].cost && edge[i].dis > edge[i].flow){
Dis[to] = Dis[t] + edge[i].cost;
Pre[to] = t;
Pre_1[to] = i;
Flow[to] = std::min(Flow[t], edge[i].dis - edge[i].flow);
if(!Used.test(to)){
Used.set(to, 1); Q.push(to);
}
}
}
}
return Flow[T];
}
int MFMS(){
int Ans = 0, res = 0, Ans_2 = 0;
while((res = Spfa()) != 0x3f3f3f3f){
Ans += res;
Ans_2 += Dis[T] * Flow[T];
int t = T;
while(t != S){
int tmp = Pre_1[t];
edge[tmp].flow += res;
edge[tmp^1].flow -= res;
t = Pre[t];
}
}
printf("%d ", Ans);
return Ans_2;
}
int main(){
// freopen("test.in", "r", stdin);
scanf("%d%d%d%d", &N, &M, &S, &T);
memset(head, -1, sizeof head);
for(reg int i = 1; i <= M; i ++){
int x, y, z, w;
scanf("%d%d%d%d", &x, &y, &z, &w);
Add(x, y, z, w), Add(y, x, 0, -w);
}
printf("%d\n", MFMS());
return 0;
}
/*
Add(x, y, z, w), Add(y, x, 0, -w);
if(Dis[to] > Dis[t] + edge[i].cost && edge[i].dis > edge[i].flow){
*/