# BZOJ 刷题总结

##背景

##PS
1.不定时更新做题的思路和吐槽
2.按照hzw刷题顺序训练，具体依照BZOJ题表
3.希望寒假能够至少刷够100道题目吧，在此立个FLAG，希望别被青岛的妖风吹跑
##Problem & Solution

#### BZOJ 1003

######题意

###### Solution

/**************************************************************
Problem: 1003
User: YuHsin
Language: C++
Result: Accepted
Time:64 ms
Memory:1388 kb
****************************************************************/

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define inf 100000000
const int N = 300;
int n, m, k, e;
int f[N];
bool vis[N][N], point[N];
struct node {
int y, d;
};
int dis[N];
bool passed[N];
vector<node> edge[N];
int spfa(int start, int endd) {
for(int i = 1; i <= m; i++)  {
point[i] = true;
for(int j = start; j <= endd; j++)  {
if (vis[i][j]) point[i] = false;
}
}
if (!point[1] || !point[m]) return inf;
queue<int> q;
for(int i = 1; i <= m; i++)  {
passed[i] = false;
dis[i] = inf;
}
dis[1] = 0; passed[1] = true;
q.push(1);
while(!q.empty())  {
int x = q.front();
q.pop();
passed[x] = false;
for(int j = 0; j < edge[x].size(); j++) {
node e = edge[x][j];
if (!point[e.y]) continue;
if (dis[e.y] > dis[x] + e.d)  {
dis[e.y] = dis[x] + e.d;
if (!passed[e.y])  {
passed[e.y] = true;
q.push(e.y);
}
}
}
}
return  dis[m];
}
int main()
{
scanf("%d%d%d%d", &n, &m, &k, &e);
for(int i = 1; i <= e; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
edge[x].push_back((node){y, z});
edge[y].push_back((node){x, z});
}
int tot;
scanf("%d", &tot);
for(int i = 1; i <= tot; i++)  {
int p, l, r;
scanf("%d%d%d", &p, &l, &r);
for(int j = l; j <= r; j++) vis[p][j] = true;
}
for(int i = 1; i <= n; i++) f[i] = inf;
for(int i = 1; i <= n; i++)  {
for(int j = 0; j < i; j++) {
int res = spfa(j + 1, i);
if (res < inf) f[i] = min(f[i], k + f[j] + (i - j) * res);
}
}
printf("%d", f[n] - k);
return 0;
}


#### BZOJ 1303

###### Solution

#include<cstdio>
#include<iostream>
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 210000;
int a[N];
int cnt1[N], cnt2[N];
int n, m;
int main()
{
int base = 100005, pos;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)  {
scanf("%d", a + i);
if (a[i] == m) pos = i;
}
int tot = base;
for(int i = pos; i > 0; i--) {
if (a[i] < m) tot--;
else if (a[i] > m) tot++;
cnt1[tot]++;
}
tot = base;
for(int i = pos; i <= n; i++)  {
if (a[i] < m) tot++;
else if (a[i] > m)  tot--;
cnt2[tot]++;
}
ll ans = 0;
for(int i = base - 100000; i <= base + 100000; i++)  ans += 1LL * cnt1[i] * cnt2[i];
cout << ans;
return 0;
}


#### BZOJ 1191

###### Solution

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 2003;
int n, m;
vector<int> edge[N];
bool used[N];
int girl[N];
bool find(int x)  {
for(int i = 0; i < edge[x].size();i++)  {
int y = edge[x][i];
if (used[y]) continue;
used[y] = true;
if (girl[y] == 0 || find(girl[y])) {
girl[y] = x;
return 1;
}
}
return 0;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)  {
int x, y;
scanf("%d%d", &x, &y);
edge[i].push_back(++x);
edge[i].push_back(++y);
}
for(int i = 1; i <= m; i++)  {
for(int i = 1; i <= n; i++) used[i] = false;
if (!find(i)) {
printf("%d", i - 1);
return 0;
}
}
printf("%d", m);
return 0;
}
﻿


#### BZOJ 1059

###### Solution

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 503;
int n, m;
bool used[N];
int girl[N];
bool a[N][N];
bool find(int x)  {
for(int j = 1; j <= n; j++) {
if (!a[x][j] || used[j]) continue;
used[j] = true;
if (girl[j] == 0 || find(girl[j])) {
girl[j] = x;
return 1;
}
}
return 0;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)  {
scanf("%d", &n);
for(int i = 1; i <= n; i++) girl[i] = 0;
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) scanf("%d", &a[i][j]);
int ans = 0;
for(int i = 1; i <= n; i++)  {
for(int j = 1; j <= n; j++) used[j] = false;
if (find(i)) ans++;
}
if (ans == n) puts("Yes");
else puts("No");
}
return 0;
}


#### BZOJ 1202

###### Solution

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 200;
int value[N][N];
int n, m;
int inf = 210000000;
struct node {
int l, r, w;
} a[3000];
bool cmp(node a, node b)  {
if (a.r == b.r)  return a.l < b.l;
return a.r < b.r;
}
bool Cal() {
for(int i = 1; i <= m; i++) {
int l = a[i].l, r = a[i].r, w = a[i].w;
if (value[r][l] != inf && value[r][l] != w)  return false;
value[r][l] = w;
for(int j = 1; j <= l - 1; j++) if (value[l - 1][j] != inf) {
if (value[r][j] != inf && value[r][j] != value[l - 1][j] + value[r][l]) return false;
value[r][j] = value[l - 1][j] + value[r][l];
}
}
return true;
}
int main()  {
int T;
scanf("%d", &T);
while(T--)  {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)  for(int j = 1; j <= i; j++) value[i][j]  = inf;
for(int i = 1; i <= m; i++)  scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].w);
sort(a + 1, a + m + 1, cmp);
if (Cal())  puts("true");  else puts("false");
}
return 0;
}

// 并查集
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<algorithm>
using namespace std;
const int N = 200;
int n, m;
int f[N], g[N];
int find(int x)  {
if (f[x] == x) return x;
int t = find(f[x]);
g[x] += g[f[x]];
return f[x] = t;
}
bool flag;
bool unio(int x, int y, int z)  {
int xx = find(x), yy = find(y);
if (xx !=  yy)  {
g[xx] = -g[x] + z + g[y];
f[xx] = yy;
}
else  if (g[x] - g[y] != z) flag = false;
}
int main()  {
int T;
scanf("%d", &T);
while(T--)  {
scanf("%d%d", &n, &m);
flag = true;
for(int i = 0; i <= n; i++) f[i] = i, g[i] = 0;
for(int i = 1; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
unio(x - 1, y, z);
}
if (flag)  puts("true");  else puts("false");
}
return 0;
}


#### BZOJ 3223

###### Solution

splay模板即可

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 1000007
int ch[N][2], f[N], size[N], cnt[N], key[N];
int sz, root;
inline void clear(int x)  {
ch[x][0] = ch[x][1] = f[x] = size[x] = cnt[x] = key[x] = 0;
}
inline bool get(int x)  {
return ch[f[x]][1] == x;
}
inline void update(int x)  {
if (x)  {
size[x] = cnt[x];
if (ch[x][0]) size[x] += size[ch[x][0]];
if (ch[x][1]) size[x] += size[ch[x][1]];
}
}
inline void rotate(int x)  {
int old = f[x], oldf = f[old], whichx = get(x);
ch[old][whichx] = ch[x][whichx^1]; f[ch[old][whichx]] = old;
ch[x][whichx^1] = old; f[old] = x;
f[x] =  oldf;
if (f[x]) ch[oldf][ch[oldf][1] == old] = x;
update(old); update(x);
}
inline void splay(int x)  {
for(int fa; (fa = f[x]); rotate(x))
if (f[fa]) rotate((get(x) == get(fa)) ? fa : x);
root = x;
}
inline void insert(int x)  {
if (root == 0)  {
sz++; ch[sz][0] =  ch[sz][1] = f[sz] = 0;
size[sz] = cnt[sz] = 1;
key[sz] = x; root = sz; return;
}
int now = root, fa = 0;
while(true)  {
if (x == key[now]) {
cnt[now]++; update(now); update(fa); splay(now); break;
}
fa = now;
now = ch[now][x > key[now]];
if (now == 0)  {
sz++; ch[sz][0] = ch[sz][1] = 0;
f[sz] = fa; key[sz] = x;
size[sz] = cnt[sz] = 1;
ch[fa][key[fa]<x] = sz;
update(fa); splay(sz); break;
}
}
}
inline int find(int x)  {
int now = root, ans = 0;
while(true)  {
if (x < key[now]) now = ch[now][0];
else {
ans += (ch[now][0]?size[ch[now][0]]:0);
if (x == key[now]) {  splay(now); return ans + 1;  }
ans += cnt[now];
now = ch[now][1];
}
}
}
inline int findx(int x)  {
int now = root;
while(true)  {
if (ch[now][0] && x <= size[ch[now][0]]) now = ch[now][0];
else {
int temp = cnt[now] + (ch[now][0]?size[ch[now][0]]:0);
if (x <= temp) return key[now];
x -= temp; now = ch[now][1];
}
}
}
inline int pre()  {
int now = ch[root][0];
while(ch[now][1]) now = ch[now][1];
return now;
}
inline int nxt()  {
int now = ch[root][1];
while(ch[now][0]) now = ch[now][0];
return now;
}
inline void del(int x)  {
int whatever = find(x);
if (cnt[root] > 1) {
cnt[root]--; update(root); return;
}
if (!ch[root][0] && !ch[root][1]) {  clear(root); root = 0; return;  }
if (!ch[root][0])  {
int oldroot = root; root = ch[root][1]; f[root] = 0;
clear(oldroot); return;
}
if (!ch[root][1])  {
int oldroot = root;  root = ch[root][0]; f[root] = 0;
clear(oldroot);  return ;
}
int leftbig = pre(), oldroot =  root;
splay(leftbig);
f[ch[oldroot][1]] = root;
ch[root][1] = ch[oldroot][1];
clear(oldroot);
update(root); return;
}
int main(){
int n,opt,x;
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%d%d",&opt,&x);
switch(opt){
case 1: insert(x); break;
case 2: del(x); break;
case 3: printf("%d\n",find(x)); break;
case 4: printf("%d\n",findx(x)); break;
case 5: insert(x); printf("%d\n",key[pre()]); del(x); break;
case 6: insert(x); printf("%d\n",key[nxt()]); del(x); break;
}
}
return 0;
}


2018.03.04

##BZOJ 1051
[Solution]

##BZOJ 1588
[Solution]

##BZOJ 1208
[Solution]
splay模板题

##BZOJ 3224
[Solution]
splay模板题

##BZOJ 1084
[Solution]

dp[ i ] [ j ] = max{ dp[i][j-1], dp[i-1][j],dp[k][j] + sum[1][k+1]~sum[1][i] (i > j, 0 <=k < i),
dp[k][k] + sum[1][k+1 i]+sum[2][k+1i](i=j, 0 < k < i ),
dp[i][k] + sum[2][k+1~j] (i < j, 0 <=k < j) }

##BZOJ 1491
[Solution]

##BZOJ 1295

##bzoj 1085