/*最小费用最大流
//给一个包含n个点和m条边的图,每条边(u,v)有一个流量限制w(u,v)和单位流量的费用c(u,v)
求出该网络的最小费用最大流,即在F(G)最大的前提下,是C(G)最小
// SPFA跑费用流 洛谷 P3381
#include<bits/stdc++.h>
using namespace std;
#define maxn 5005
int read(){
char c=getchar();
int f = 1, ans = 0;
while(c < '0' || c > '9'){
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
ans = ans*10 + c - '0';
c = getchar();
}
return ans*f;
}
int s, t, cost[maxn], head[maxn], vis[maxn], flow[maxn], pre[maxn], last[maxn], cnt = -1;
struct node{
int to, next, cost, flow;
}p[maxn*20];
queue<int> q;
void add(int x, int y, int f, int c){
p[++cnt].next = head[x];
head[x] = cnt;
p[cnt].cost = c;
p[cnt].flow = f;
p[cnt].to = y;
}
bool spfa(){
memset(vis, 0, sizeof(vis));
memset(cost, 0x7f, sizeof(cost));
flow[s] = 0x7ffffff;
q.push(s), vis[s] = 1, cost[s] = 0, pre[t] = -1;
while(!q.empty()){
int now = q.front();
q.pop();
vis[now] = 0;
for(int k = head[now]; k != -1; k = p[k].next){
int x = p[k].to;
if(p[k].flow > 0 && cost[x] > cost[now] + p[k].cost){
cost[x] = cost[now] + p[k].cost;
pre[x] = now;
last[x] = k;
flow[x] = min(flow[now], p[k].flow);
if(!vis[x]){
vis[x] = 1;
q.push(x);
}
}
}
}
return pre[t] != -1;
}
int maxflow, mincost;
void MCMF(){
while(spfa()){
int now = t;
maxflow += flow[t];
mincost += flow[t]*cost[t];
while(now != s){
p[last[now]].flow -= flow[t];
p[last[now]^1].flow += flow[t];
now = pre[now];
}
}
}
int main(){
memset(head, -1, sizeof(head));
int n, m, x, y, c, f;
n = read(), m = read(), s = read(), t = read();
for(int i = 1; i <= m; i++){
x = read(), y = read(), f = read(), c = read();
add(x, y, f, c);add(y, x, 0, -c);
}
MCMF();
printf("%d %d\n",maxflow,mincost);
return 0;}
*/
/*网络最大流:给一个网络图,以及其源点和汇点,求出其网络最大流
//注意流量的定义
// 洛谷 P3376
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long LL;
const int maxn = 1e3 + 5;
const int inf = 1<<30;
int n, m, s, t, cnt;
int head[maxn], cur[maxn], dep[maxn];
queue<int> q;
struct node{
int next, v;
LL dis;
}edge[maxn << 5];
void add(int u, int v, LL dis){
edge[cnt].v = v;
edge[cnt].next = head[u];
edge[cnt].dis = dis;
head[u] = cnt++;
}
bool bfs(){
memset(dep, 0x7f, sizeof(dep));
for(int i = 1; i <= n; i++) cur[i] = head[i];
dep[s] = 0;
q.push(s);
while(!q.empty()){
int now = q.front();
q.pop();
for(int k = head[now]; ~k; k = edge[k].next){
int v = edge[k].v;
if(dep[v] > inf && edge[k].dis){
dep[v] = dep[now] + 1;
q.push(v);
}
}
}
return dep[t] < inf;
}
LL dfs(int now, int limit){
if(!limit || now == t) return limit;
LL flow = 0, ins;
for(int k = cur[now]; ~k; k = edge[k].next){
cur[now] = k;
int v = edge[k].v;
if(dep[v] == dep[now] + 1 && (ins = dfs(v, min(LL(limit), edge[k].dis)))){
flow += ins;
limit -= ins;
edge[k].dis -= ins;
edge[k^1].dis += ins;
if(!limit) break;
}
}
return flow;
}
LL Dinic(){
LL maxflow = 0;
while(bfs())
maxflow += dfs(s, inf);
return maxflow;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> s >> t;
memset(head, -1, sizeof(head));
int u, v;
LL c;
for(int i = 1; i <= m; i++){
cin >> u >> v >> c;
add(u, v, c);
add(v, u, 0);
}
cout << Dinic() << endl;
return 0;}
*/
/*二分图匹配匈牙利算法
//给定一个二分图,其左部点的个数为n,右部点的个数为m,边数为e,求最大匹配的边数
// 匈牙利算法 洛谷 P3386
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
struct node{
int v, next;
}tree[maxn];
int cnt, head[1005], cx[1005], cy[1005];
bool vis[1005];
int dfs(int u){
for(int k = head[u]; k; k = tree[k].next){
int v = tree[k].v;
if(!vis[v]){
vis[v] = true;
if(!cy[v] || dfs(cy[v])){
cx[u] = v;
cy[v] = u;
return 1;
}
}
}
return 0;
}
int read(){
char c = getchar();
int f = 1, ans = 0;
while(c < '0' || c > '9'){
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
ans = ans*10 + c - '0';
c = getchar();
}
return ans*f;
}
int main(){
int i, n, m, e, u, v, ans = 0;
n = read(), m = read(), e = read();
for(i = 1; i <= e; i++){
u = read(), v = read();
if(u > n || v > m) continue;
tree[++cnt].v = v;
tree[cnt].next = head[u];
head[u] = cnt;
}
for(i = 1; i <= n; i++){
if(head[i] && !cx[i]){
memset(vis, 0, sizeof(vis));
ans += dfs(i);
}
}
printf("%d\n",ans);
return 0;}
*/
/*LCA最近公共祖先ST表
// ST表版本 洛谷 P3379
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
int dp[maxn][(int)log2(maxn) + 2], dep[maxn<<1], fa[maxn], first[maxn], cnt, ver[maxn], tol;
int head[maxn];
int read(){
char c = getchar();
int f = 1, ans = 0;
while(c < '0' || c > '9'){
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
ans = ans*10 + c - '0';
c = getchar();
}
return ans*f;
}
struct node{
int next, v;
}tree[maxn<<1];
void dfs(int v, int f, int d){
first[v] = ++cnt;
fa[v] = f;
dep[cnt] = d;
ver[cnt] = v;
for(int k = head[v]; ~k; k = tree[k].next){
if(tree[k].v == f) continue;
dfs(tree[k].v, v, d + 1);
dep[++cnt] = d;
ver[cnt] = v;
}
}
void ST(){
for(int i = 1; i <= cnt; i++)
dp[i][0] = i;
for(int j = 1; (1<<j) <= cnt; j++){
int s = 1<<j;
for(int i = 1; i + s - 1 <= cnt; i++){
int a = dp[i][j - 1], b = dp[i + (1<<(j-1))][j - 1];
dp[i][j] = dep[a] < dep[b] ? a : b;
}
}
}
int RMQ(int x, int y){
x = first[x], y = first[y];
if(x > y) swap(x, y);
int k = (int)floor(log2(y - x + 1));
int a = dp[x][k], b = dp[y - (1<<k) + 1][k];
return ver[dep[a] < dep[b] ? a : b];
}
void add(int x, int y){
tree[++tol].v = y;
tree[tol].next = head[x];
head[x] = tol;
}
int main(){
int x, y, m, n, root, i;
n = read(), m = read(), root = read();
memset(head, -1, sizeof(head));
for(i = 1; i < n; i++){
x = read(), y = read();
add(x, y);
add(y, x);
}
dfs(root, 0, 1);
ST();
for(i = 1; i <= m; i++){
x = read(), y = read();
printf("%d\n", RMQ(x,y));
}
return 0;}
*/
/*树上任意两点距离之和
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 100005;
const ll mod=1e9+7;
int sum[maxn], n;
ll dp[maxn];
struct Edge
{
int v, w;
};
vector<Edge> tree[maxn];
void dfs(int cur, int father)
{
sum[cur] = 1;
for(int i = 0; i < tree[cur].size(); i++)
{
int son = tree[cur][i].v;
ll len = tree[cur][i].w;
if(father == son)
continue;
dfs(son, cur);
sum[cur] += sum[son];
sum[cur]%=mod;
dp[cur] =(dp[cur]+dp[son] + (((n-sum[son])*sum[son])%mod * len)%mod)%mod;
}
}
int main()
{
std::ios::sync_with_stdio(false);
calJc();
while(cin>>n)
{
for(int i = 0; i <= n; i++)
tree[i].clear();
memset(sum, 0, sizeof(sum));
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n-1; i++)
{
ll u,v,w;
cin>>u>>v>>w;
Edge t1, t2;
t1.v = v;
t1.w = w;
t2.v = u;
t2.w = w;
tree[u].push_back(t1);
tree[v].push_back(t2);
}
dfs(1,0);
cout<<dp[1]<<endl;
}
return 0;
}
*/
/*拓扑排序
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int MAX_N=10000;
struct edge
{
int to,next;
}e[MAX_N];
int p[MAX_N],eid;
void init()
{
eid=0;
memset(p,-1,sizeof(p));
}
void insert(int u,int v)
{
e[eid].to=v;
e[eid].next=p[u];
p[u]=eid++;
}
int indegree[MAX_N];
int n;
int topo()
{
queue<int>Q;
for(int i=1;i<=n;i++)
{
if(indegree[i]==0)
Q.push(i);
}
while(!Q.empty())
{
int now=Q.front();
cout<<"visting"<<now<<endl;
Q.pop();
for(int i=p[now];i!=-1;i=e[i].next)
{
int v=e[i].to;
indegree[v]--;
if(indegree[v]==0)
Q.push(v);
}
}
}
//LeetCode课程表问题,给定课程总量以及他们的先决条件[0,1],返回你为了学完所有课程所安排的学习顺序
class Solution {
private:
// 存储有向图
vector<vector<int>> edges;
// 标记每个节点的状态:0=未搜索,1=搜索中,2=已完成
vector<int> visited;
// 用数组来模拟栈,下标 0 为栈底,n-1 为栈顶
vector<int> result;
// 判断有向图中是否有环
bool valid = true;
public:
void dfs(int u) {
// 将节点标记为「搜索中」
visited[u] = 1;
// 搜索其相邻节点
// 只要发现有环,立刻停止搜索
for (int v: edges[u]) {
// 如果「未搜索」那么搜索相邻节点
if (visited[v] == 0) {
dfs(v);
if (!valid) {
return;
}
}
// 如果「搜索中」说明找到了环
else if (visited[v] == 1) {
valid = false;
return;
}
}
// 将节点标记为「已完成」
visited[u] = 2;
// 将节点入栈
result.push_back(u);
}
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
edges.resize(numCourses);
visited.resize(numCourses);
for (const auto& info: prerequisites) {
edges[info[1]].push_back(info[0]);
}
// 每次挑选一个「未搜索」的节点,开始进行深度优先搜索
for (int i = 0; i < numCourses && valid; ++i) {
if (!visited[i]) {
dfs(i);
}
}
if (!valid) {
return {};
}
// 如果没有环,那么就有拓扑排序
// 注意下标 0 为栈底,因此需要将数组反序输出
reverse(result.begin(), result.end());
return result;
}
};
*/
/*线段树 区间加区间乘混合
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
typedef long long LL;
const int maxn = 1e5 + 5;
LL mod = 571373;
LL tree[maxn << 2], lazy[maxn << 2], mul[maxn << 2], a[maxn];
inline void push_up(int rt){
tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % mod;
}
inline void build(int l, int r, int rt){
if(l == r){
tree[rt] = a[l];
mul[rt] = 1;
}
else{
int m = l + r >> 1;
mul[rt] = 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
push_up(rt);
}
}
inline void push_down(int l, int r, int rt){
int m = l + r >> 1, r1 = rt << 1, r2 = rt << 1 | 1;
tree[r1] = (tree[r1] * mul[rt] + lazy[rt] * (m - l + 1)) % mod;
tree[r2] = (tree[r2] * mul[rt] + lazy[rt] * (r - m)) % mod;
lazy[r1] = (lazy[r1] * mul[rt] + lazy[rt]) % mod;
lazy[r2] = (lazy[r2] * mul[rt] + lazy[rt]) % mod;
lazy[rt] = 0;
mul[r1] = mul[r1] * mul[rt] % mod;
mul[r2] = mul[r2] * mul[rt] % mod;
mul[rt] = 1;
}
inline void update1(int l, int r, int L, int R, LL c, int rt){
if(L <= l && r <= R){
tree[rt] = (tree[rt] + c * (r - l + 1)) % mod;
lazy[rt] = (lazy[rt] + c) % mod;
return;
}
push_down(l, r, rt);
int m = l + r >> 1;
if(L <= m) update1(l, m, L, R, c, rt << 1);
if(R > m) update1(m + 1, r, L, R, c, rt << 1 | 1);
push_up(rt);
return;
}
inline void update2(int l, int r, int L, int R, int c, int rt){
if(L <= l && r <= R){
tree[rt] = tree[rt] * c % mod;
mul[rt] = mul[rt] * c % mod;
lazy[rt] = lazy[rt] * c % mod;
return;
}
push_down(l, r, rt);
int m = l + r >> 1;
if(L <= m) update2(l, m, L, R, c, rt << 1);
if(R > m) update2(m + 1, r, L, R, c, rt << 1 | 1);
push_up(rt);
}
inline int query(int l, int r, int L, int R, int rt){
if(L <= l && r <= R) return tree[rt];
push_down(l, r, rt);
int m = l + r >> 1, ans = 0;
if(L <= m) ans = query(l, m, L, R, rt << 1);
if(R > m) ans = (ans + query(m + 1, r, L, R, rt << 1 | 1)) % mod;
return ans;
}
int main(){
IOS;
int n, m, l, r, c, flag;
cin >> n >> m >> mod;
for(int i = 1; i <= n; i++) cin >> a[i];
build(1, n, 1);
while(m--){
cin >> flag;
switch(flag){
case 1 :
cin >> l >> r >> c;
update2(1, n, l, r, c, 1);
break;
case 2 :
cin >> l >> r >> c;
update1(1, n, l, r, c, 1);
break;
case 3 :
cin >> l >> r;
cout << query(1, n, l, r, 1) << endl;
}
}
}
*/
/*ST表
// 求区间最值 洛谷 P3865
// 给定一个长度为N的数列,和M次询问,求出每一次询问的区间内数字的最大值
#include<bits/stdc++.h>
using namespace std;
int n, k, num[100005];
int ma[100005][25]; // n*logn
void pre(){
for(int i = 1; i <= n; i++)
ma[i][0] = num[i];
int s = 2, s2;
for(int j = 1; s <= n; j++, s <<= 1){
s2 = s;
for(int i = 1; s2 <= n; i++, s2++)
ma[i][j] = max(ma[i][j - 1], ma[i + (s>>1)][j - 1]);
}
}
int qerry(int l, int r){
int k = trunc(log2(r-l+1)); // floor
return max(ma[l][k], ma[r - (1 << k) + 1][k]);
}
// 精髓就是这个区间查询,按区间长度找到对应层级
int main(){
int q;
cin >> n >> q;
for(int i = 1; i <= n; i++)
cin >> num[i];
pre();
int l, r;
for(int i = 1; i <= q; i++){
cin >> l >> r;
cout << qerry(l,r)) << endl;
}
return 0;
}
// ST表还可以通过时间戳找LCA
*/