# 数据结构

### 单调栈

https://xlor.cn/2019/4/2019nanchang/

## 笛卡尔树

### Equivalent Prefixes-前缀笛卡尔树

$$max(ans)$$;

#include <bits/stdc++.h>
#include<stdint.h>
#define int long long
#define scan(n) scanf("%lld", &(n))
#define scann(n, m) scanf("%lld%lld", &(n), &(m))
#define scannn(a, b, c) scanf("%lld%lld%lld", &(a), &(b), &(c))
#define prin(n) printf("%lld", (n))
#define pb push_back
#define mp make_pair
#define ms(a) memset(a, 0, sizeof(a))
#define fo(i, a, b) for (int i = (a); i <= (b); i++)
#define ro(i, a, b) for (int i = (a); i >= (b); i--)
const int inf = 0x3f3f3f3f;
using namespace std;
const int maxn = 1e5+100;
int n;
int a[maxn],b[maxn];
int s1[maxn],s2[maxn];
int32_t main() {
while(scan(n)!=EOF){
fo(i,1,n)scan(a[i]);
fo(i,1,n)scan(b[i]);
int maxpos=1;
fo(i,1,n){
if(tail1!=tail2)break;
s1[++tail1]=a[i],s2[++tail2]=b[i];
maxpos=i;
}
cout<<maxpos<<endl;
}
return 0;
}


### 笛卡尔树习题

http://acm.hdu.edu.cn/showproblem.php?pid=6305

https://blog.csdn.net/zhaiqiming2010/article/details/80245872

## Bitset

#include<bits/stdc++.h>
using namespace std;

bitset<5> b, a;
int main() {
cout << b << endl; //00000

b.set(2);
cout << b << endl;//00100

a.set(3);
cout << a << endl;//01000

b ^= a;//(00100)^(01000)
cout << b << endl;//01100

b.reset(3);//00100
cout << b << endl;

b.flip();//11011
cout << b << endl;
}


## LCA

### [CF1304E]1-Trees and Queries

https://codeforces.com/contest/1304/problem/E

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
int head[maxn], to[maxn * 2], nxt[maxn * 2], d[maxn * 2], tot;
int n, m;
void add(int x, int y, int w){
to[++tot] = y; nxt[tot] = head[x]; d[tot] = w; head[x] = tot;
}
int dp[maxn][20], dep[maxn], dis[maxn];
void dfs(int u, int fa){
dp[u][0] = fa; dep[u] = dep[fa] + 1;
for (int i = head[u]; i; i = nxt[i]){
int v = to[i];
if (v == fa) continue;
dis[v] = dis[u] + d[i];
dfs(v, u);
}
}
void init(){
memset(dp, 0, sizeof(dp));
dep[0] = dis[0] = 0;
dfs(1, 0);
for (int j = 1; j < 20; j++)
for (int i = 1; i <= n; i++)
dp[i][j] = dp[dp[i][j - 1]][j - 1];
}
int qlca(int x, int y){
if (dep[x] < dep[y]) swap(x, y);
int tmp = dep[x] - dep[y];
for (int i = 0; tmp; i++, tmp >>= 1)
if (tmp & 1) x = dp[x][i];
if (x == y) return x;
for (int i = 19; i >= 0; i--){
if (dp[x][i] != dp[y][i]){
x = dp[x][i]; y = dp[y][i];
}
}
return dp[x][0];
}
int dist(int x,int y) {
int u = qlca(x, y);
int ans =  dis[x] + dis[y] - 2*dis[u];
return dis[x] + dis[y] - 2*dis[u];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n-1;i++) {
int x, y;
scanf("%d%d", &x, &y);
}
init();
int q;
scanf("%d", &q);
while(q--) {
int a, b, x, y,k;
scanf("%d%d%d%d%d", &x, &y, &a, &b, &k);
int d = dist(a, b);
if(k>=d&&(k-d)%2==0) {
printf("YES\n");
continue;
}
else {
d = dist(a,x)+dist(b,y)+1;
if(k>=d&&(k-d)%2==0) {
printf("YES\n");
continue;
}
d = dist(a,y)+dist(b,x)+1;
if(k>=d&&(k-d)%2==0) {
printf("YES\n");
continue;
}
}
printf("NO\n");
}
}


## 树状数组

### Codeforces1324DPair of Topics

https://codeforces.com/contest/1324/problem/D

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int a[maxn];
int b[maxn];
int c[maxn];
struct Node
{
int v, index;
bool operator<(const Node& b) const {
if(v==b.v) {
return index <b.index;//注意这里!!
}
return v < b.v;  //从小到大排序
}
}node[maxn];
int n;
{
while(i<=n*2)
{
c[i]++;
i+=i&(-i);
}
}
int sum(int i)
{
int res=0;
while(i>0)
{
res+=c[i];
i-=i&(-i);
}
return res;
}
vector<int> v;
int main() {
scanf("%d", &n);
for(int i=1;i<=n;i++) {
scanf("%d", &a[i]);
}
for(int i=1;i<=n;i++) {
scanf("%d", &b[i]);
}
for (int i = 1; i <= n;i++) {
node[i].v = a[i] - b[i];
node[i].index = i;
node[i + n].v = b[i] - a[i];
node[i + n].index = i + n;
}
long long ans = 0;
sort(node + 1, node + 1 + 2 * n);
for (int i = 2*n; i >=1;i--) {
int id = node[i].index;
int v = node[i].v;
if(id<=n) {
continue;
}
if(v<0)
ans--;
ans += sum(id - n);
}

cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
int a[maxn], b[maxn], c[maxn * 2];
int lowbit(int x) {
return x & (-x);
}

while(i<maxn*2) {
c[i] += d;
i += lowbit(i);
}
}

int query(int i) {
int ret = 0;
while(i>0) {
ret += c[i];
i -= lowbit(i);
}
return ret;
}

vector<int> v;

int main() {
int n;
scanf("%d", &n);
for(int i=1;i<=n;i++) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n;i++) {
scanf("%d", &b[i]);
}
for (int i = 1; i <= n;i++) {
v.push_back(a[i] - b[i]);
v.push_back(b[i] - a[i]);
}
long long ans = 0;
sort(v.begin(), v.end());
for (int i = 1;i<=n;i++) {
int x = b[i] - a[i];
int y = a[i] - b[i];
int id = upper_bound(v.begin(), v.end(), x) - v.begin() + 1;
int id2 = upper_bound(v.begin(), v.end(), y) - v.begin() + 1;
ans += (i - 1 - query(id));
}
cout << ans << endl;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
vector<int> v;
int a[maxn],b[maxn];

int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n;i++) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n;i++) {
scanf("%d", &b[i]);
v.push_back(a[i] - b[i]);
}
sort(v.begin(), v.end());
long long ans = 0;
for (int i = 1; i <= n;i++) {
int id = upper_bound(v.begin(), v.end(), b[i] - a[i]) - v.begin();
ans += (n  - id);
if(a[i]-b[i]>b[i]-a[i])
ans--;
}
ans /= 2;
cout << ans << endl;
}


## 树

### [CF1325C] Ehab and Path-etic MEXS

https://codeforces.com/contest/1325/problem/C

​ 对于所有不经过0的路径,mex = 0

​ 对于所有不经过1\2,但经过0的路径,mex = 1\2

​ 这样就可以满足所有情况

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 5;
struct node{
int to, id;
};
vector<node> e[maxn];
int x[maxn], y[maxn];
int vis[maxn];
int ans[maxn];
int l, r;
void dfs(int u,int fa) {
int sz = e[u].size();
for (int i = 0; i < sz;i++) {
int v = e[u][i].to;
int id = e[u][i].id;
if(v==fa||vis[id])
continue;
ans[id] = l++;
}
for (int i = 0;i<sz;i++) {
int v = e[u][i].to;
int id = e[u][i].id;
if(v==fa||vis[id])
continue;
vis[id]++;
dfs(v, u);
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n - 1;i++) {
scanf("%d %d", &x[i], &y[i]);
e[x[i]].push_back((node){y[i], i});
e[y[i]].push_back((node){x[i], i});
}
l = 0, r = n - 2;
int d = 0;
int m = 0;
for (int i = 1; i <= n;i++) {
int sz = e[i].size();
if(sz>d) {
d = sz;
m = i;
}
}

dfs(m, -1);
for (int i = 0; i < n-1;i++) {
printf("%d\n", ans[i]);
}
return 0;
}


### [CF1325F]Ehab's Last Theorem

 if(!vis[u]) {
for(int v:e[u]) {
vis[v] = 1;
}
}


u必然不会存在与一个长度大于t的环当中,那么它必然在独立集里,则把它的连边全部标记起来。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
int t;
int dep[maxn];
int f[maxn],vis[maxn];
vector<int> e[maxn];
void dfs(int u,int fa) {
for(int v:e[u]) {
if(!dep[v]) {
dep[v] = dep[u] + 1;
f[v] = u;
dfs(v, u);
}
else {
if(dep[v]-dep[u]+1>=t) {
printf("2\n");
int len = dep[v] - dep[u] + 1;
printf("%d\n", len);
int cnt = 0;
while(v) {
if(cnt==len)
break;
cnt++;
printf("%d ", v);
v = f[v];
}
exit(0);
}
}
}
if(!vis[u]) {
for(int v:e[u]) {
vis[v] = 1;
}
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
t = ceil(sqrt(n));
for (int i = 1; i <= m;i++) {
int x, y;
scanf("%d%d", &x, &y);
e[x].push_back(y);
e[y].push_back(x);
}
dep[1] = 1;
dfs(1, 0);
printf("1\n");
int cnt = 0;
for (int i = 1; i <= n;i++) {
if(cnt==t)
break;
if(!vis[i]) {
printf("%d ", i);
cnt++;
}
}
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
set<pair<int,int> > s;
vector<int> v[maxn];
bool del[maxn];
int deg[maxn],occ[maxn];
void remove(int x)
{
if (del[x])
return;
s.erase({deg[x],x});
del[x]=1;
for (int u:v[x])
{
if (!del[u])
{
s.erase({deg[u],u});
deg[u]--;
s.insert({deg[u],u});
}
}
}

int main()
{
int n, m,sq;
scanf("%d%d",&n,&m);
sq = ceil(sqrt(n));
while (m--)
{
int a,b;
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
deg[a]++;
deg[b]++;
}

for (int i=1;i<=n;i++)
s.insert({deg[i],i});
vector<int> ans;
while (!s.empty())
{
auto p=*s.begin();
s.erase(s.begin());
if (p.first+1>=sq)//度数大于等于sq-1
{
printf("2\n");
vector<int> d({p.second});
occ[p.second]=1;
while (1)
{
pair<int,int> nex(1e9,0);
for (int u:v[d.back()])
{
if (!del[u])
nex=min(nex,make_pair(occ[u],u));
}
if (nex.first)
{
printf("%d\n",(int)d.size()-nex.first+1);
for (int i=nex.first-1;i<d.size();i++)
printf("%d ",d[i]);
return 0;
}
d.push_back(nex.second);
occ[nex.second]=d.size();
}
}
//度数小于sq-1
ans.push_back(p.second);
remove(p.second);//删除所有邻边
for (int u:v[p.second])//双向删除
remove(u);
}
printf("1\n");
for (int i=0;i<sq;i++)
printf("%d ",ans[i]);
}


### [CF1139C] Edgy Tree

https://codeforces.com/contest/1139/problem/C

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
vector<int> e[maxn];
int vis[maxn];
const long long mod = 1e9 + 7;
#define add(x, y) (x + y) % mod;
int dfs(int u,int fa) {
int sz = e[u].size();
long long ret = 1;
vis[u]++;
for (int i = 0; i < sz;i++) {
int v = e[u][i];
if(v==fa||vis[v]){
continue;
}
ret += dfs(v, u);
}
return ret;
}
long long qpow(long long x,int k) {
long long ret = 1;
while(k) {
if(k&1)
ret = ret * x % mod;
x = x * x % mod;
k >>= 1;
}
return ret;
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n - 1;i++) {
int x, y, w;
scanf("%d%d%d", &x, &y, &w);
if(!w) {
e[x].push_back(y);
e[y].push_back(x);
}
}
long long sum = 0;
for (int i = 1; i <= n; i++) {
if (vis[i])
continue;
long long cnt = dfs(i, -1);
long long x = qpow(cnt, k);