#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
#define rop(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,a,b) for(int i=(a);i>(b);--i)
#define ll long long
namespace chamber{
inline void swep(auto &_,auto &__){_^=__^=_^=__;};
inline auto exgcd(auto a,auto b,auto &x,auto &y,auto c){if(!b){x=c/a;y=0;if(c%a)a=-1;return a;}int g=exgcd(b,a%b,y,x,c);y-=a/b*x;x=x%(b/g);y=(c-a*x)/b;return g;}
inline ll lread(){char c;ll x(0),y(1);c=getchar();while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}return x*y;}
inline int iread(){char c;int x(0),y(1);c=getchar();while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}return x*y;}
inline auto gcd(auto a,auto b){if(b==0) return a;else return gcd(b,a%b);}
inline auto qpow(auto a,auto b,auto p){ll res(1);while(b){if(b&1)res=res*1ll*a%p;a=a*1ll*a%p;b>>=1;}return res;}
inline auto lowbit_l(auto x){return x&-x;}
const int P[11]={2,3,5,7,9,11,13,17,19,23,39};
inline bool mr(auto x){FOR(i,0,11)if(x==P[i])return 1;auto u=x-1,t=0;while(u%2==0){u>>=1;++t;}FOR(i,0,11){auto a=P[i];auto v=qpow(a,u,x);if(v==1) continue;auto s=0;for(s=0;s<t;++s){if(v==x-1) break;v=v*1ll*v%x;}if(s==t) return 0;}return 1;}
inline void chmax(auto &_,auto __){if(_<__)_=__;}
inline void chmin(auto &_,auto __){if(_>__)_=__;}
inline ll bsgs(auto a,auto b,auto p){std::map<ll,ll> hs;b%=p;ll t=sqrt(p)+1;rop(i,0,t){hs[b*qpow(a,i,p)%p]=i;}a=qpow(a,t,p);if(!a)return (!b ? 1 : -1);FOR(i,1,t){ll val=qpow(a,i,p);ll j=(hs.find(val)==hs.end() ? -1 : hs[val]);if(j>=0&&i*t-j>=0) return i*t-j;}return -1;}
inline void excrt(auto &A,auto &P,auto a,auto p){ll x=0,y=0;ll g=exgcd(p,-P,x,y,A-a);g=(g<0 ? -g : g);P=p/g*P;A=a+qpow(x,p,P);A=(A%P+P)%P;}
}
const int N=1e5+5;
const int M=1e5+5;
namespace cb_graph{
struct no_dis_edge{
int frt[N],to[N<<1],top,nxt[N<<1];
inline void add(int u,int v){nxt[++top]=frt[u];frt[u]=top;to[top]=v;}
inline void double_add(int u,int v){add(u,v);add(v,u);}
};
struct dis_edge{
int frt[N],to[N<<1],top,nxt[N<<1];ll dis[N];
inline void add(int u,int v,auto w){nxt[++top]=frt[u];frt[u]=top;to[top]=v;dis[top]=w;}
inline void double_add(int u,int v,int w){add(u,v,w);add(v,u,w);}
};
}
namespace cb_BCJ{
struct zip_BCJ{
int f[N];
inline void init(int n){FOR(i,1,n) f[i]=i;}
inline int f_find(int x){return (f[x]==x ? x : f[x]=f_find(f[x]));}
inline void f_push(int x,int y){int fx=f_find(x),fy=f_find(y);f[fx]=fy;}
inline void easy_push(int x,int y){f[x]=y;}
};
struct sz_BCJ{
int f[N],sz[N];
inline void init(int n){FOR(i,1,n){f[i]=i;sz[i]=1;}}
inline int f_find(int x){return (f[x]==x ? x : f_find(f[x]));}
inline void f_push(int x,int y){int fx=f_find(x),fy=f_find(y);if(fx==fy) return;if(sz[fx]>sz[fy]) chamber::swep(fx,fy);f[fx]=fy;sz[fy]+=sz[fx];}
};
}
namespace cb_fast_read{
char *p1,*p2,buf[10010];
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,10000,stdin),p1==p2)?EOF:*p1++)
inline int iread(){register int x=0;register char c=gc();while(c<48)c=gc();while(c>47)x=(x<<3)+(x<<1)+(c^48),c=gc();return x;}
inline ll lread(){register ll x=0;register char c=gc();while(c<48)c=gc();while(c>47)x=(x<<3)+(x<<1)+(c^48),c=gc();return x;}
}
namespace cb_STL{
const int P=333331;
#define ls (nw<<1)
#define rs (nw<<1|1)
struct hash_table{
int frt[P+5],nxt[P+5],top;
ll dis[P+5];
std::string to[P+5];
int c=3331;
inline int H(std::string s){int a=0,b=c;rop(i,0,s.size()){a=(a+s[i]*b%P)%P;b=b*c%P;}return a+1;}
inline void push(std::string s,ll x){int hs=H(s);nxt[++top]=frt[hs];frt[hs]=top;dis[top]=x;to[top]=s;}
inline ll find(std::string s){int hs=H(s);for(int i=frt[hs];i;i=nxt[i]){if(to[i]==s) return dis[i];}return 0;}
};
#define FA (nw>>1)
struct xgdui{
ll val[N],tot;
inline void up(int nw){while(FA!=0&&val[nw]<val[FA]){chamber::swep(val[nw],val[FA]);nw=FA;}}
inline void down(int nw){while(rs<=tot&&std::min(val[ls],val[rs])<val[nw]){if(val[ls]<val[rs]){chamber::swep(val[nw],val[ls]);nw=ls;}else{chamber::swep(val[nw],val[rs]);nw=rs;}}if(ls<=tot&&val[ls]<val[nw]){chamber::swep(val[nw],val[ls]);}}
inline void push(int w){val[++tot]=w;up(tot);}
inline int top(){return val[1];}
inline void pop(){val[1]=val[tot--];down(1);}
inline void erase(int x){val[x]=val[tot--];up(x);down(x);}
};
struct dgdui{
ll val[N],tot;
inline void up(int nw){while(FA!=0&&val[nw]>val[FA]){chamber::swep(val[nw],val[FA]);nw=FA;}}
inline void down(int nw){while(rs<=tot&&std::min(val[ls],val[rs])>val[nw]){if(val[ls]>val[rs]){chamber::swep(val[nw],val[ls]);nw=ls;}else{chamber::swep(val[nw],val[rs]);nw=rs;}}if(ls<=tot&&val[ls]>val[nw]){chamber::swep(val[nw],val[ls]);}}
inline void push(int w){val[++tot]=w;up(tot);}
inline int top(){return val[1];}
inline void pop(){val[1]=val[tot--];down(1);}
inline void erase(int x){val[x]=val[tot--];up(x);down(x);}
};
struct STACK{
ll val[N],top_;
inline void pop(){--top_;}
inline void push(int x){val[++top_]=x;}
inline int top(){return val[top_];}
inline int size(){return top_;}
inline bool empty(){return top_==0;}
inline int get(int x){return val[x];}
};
struct QUEUE{
int val[N],head=0,tail=0,p=chamber::qpow(2,17,N<<1)-1;
inline void pop(){++head;}
inline void push(int x){val[tail&p]=x;++tail;}
inline int front(){return val[head&p];}
inline int size(){return tail-head;}
inline bool empty(){return (tail-head==0 ? 1 : 0);}
inline int back(){return val[(tail-1)&p];}
inline int get(int x){return val[(head+x-1)&p];}
};
struct DEQUE{
int val[2*N],head=N,tail=N;
inline void push_front(int x){val[--head]=x;}
inline void push_back(int x){val[tail++]=x;}
inline void pop_back(){--tail;}
inline void pop_front(){++head;}
inline int back(){return val[tail-1];}
inline int front(){return val[head];}
inline int size(){return tail-head;}
inline int get(int x){return val[head+x-1];}
};
}
const int mod=998244353;
namespace cb_comb{
ll c[N]={1};
inline void init(){FOR(i,1,N-5) c[i]=c[i-1]*i%mod;}
inline ll C(int n,int m){if(m>n||n<0||m<0) return 0;return c[n]*chamber::qpow(c[m],mod-2,mod)%mod*chamber::qpow(c[n-m],mod-2,mod)%mod;}
}
namespace cb_ny{
int pm[N],tot,vis[N],bj[N],phi[N];
inline void init_(ll n){bj[1]=1;FOR(i,2,n){if(bj[i]==0){pm[++tot]=i;phi[i]=i-1;}for(int j=1;j<=tot&&pm[j]*i<=n;++j){bj[pm[j]*i]=1;if(!(i%pm[j])){phi[i*pm[j]]=phi[i]*pm[j];break;}else{phi[i*pm[j]]=phi[i]*phi[pm[j]];}}}}
ll inv[N],c[N];
inline ll getny(auto x,auto p){return qpow(x,phi[p],p);}
inline void init(auto n,auto p){init_(n);FOR(i,1,n){c[i]=(c[i-1]*1ll*i)%p;}inv[n]=getny(c[n],p);RFOR(i,n-1,1){inv[i]=(inv[i+1]*1ll*(i+1))%p;}FOR(j,1,n){inv[j]=inv[j]*1ll*c[j-1]%p;}}
}
namespace cb_blah{
struct DIJ{
ll ds[N];
bool vis[N];
cb_graph::dis_edge e;
std::priority_queue<std::pair<ll,int> >q;
inline void work(int s){q.push(std::make_pair(0,s));memset(ds,0x7f7f7f,sizeof ds);ds[s]=0;while(!q.empty()){int u=q.top().second;ll w=-q.top().first;while(vis[u]&&!q.empty()){q.pop();u=q.top().second;w=-q.top().first;}if(q.empty()) break;else q.pop();vis[u]=1;for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];ll z=e.dis[i];if(ds[v]>w+z){ds[v]=w+z;q.push(std::make_pair(-ds[v],v));}}}}
};
struct SPFA{
cb_graph::dis_edge e;
int ds[N],cnt[N];
bool vis[N];
cb_STL::QUEUE q;
inline void work(int s){memset(ds,0x3f3f3f3f,sizeof ds);memset(cnt,0,sizeof cnt);memset(vis,0,sizeof vis);while(!q.empty()) q.pop();q.push(1);ds[s]=0;vis[s]=1;while(!q.empty()){int u=q.front();vis[u]=0;q.pop();for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];int w=e.dis[i];if(ds[u]+w<ds[v]){ds[v]=ds[u]+w;if(!vis[v]){vis[v]=1;q.push(v);}}}}}
};
struct fuhuan{
cb_graph::dis_edge e;
inline bool work(int n){int ds[N],cnt[N];bool vis[N];cb_STL::QUEUE q;memset(ds,0x3f3f3f3f,sizeof ds);memset(cnt,0,sizeof cnt);memset(vis,0,sizeof vis);while(!q.empty()) q.pop();q.push(1);ds[1]=0;vis[1]=1;cnt[1]=1;while(!q.empty()){int u=q.front();vis[u]=0;q.pop();for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];int w=e.dis[i];if(ds[u]+w<ds[v]){ds[v]=ds[u]+w;if(cnt[u]+1>n){return 1;}cnt[v]=cnt[u]+1;if(!vis[v]){vis[v]=1;q.push(v);}}}}return 0;}
};
struct KUR{
#define P std::pair<ll,std::pair<int,int>>
cb_BCJ::zip_BCJ F;
std::priority_queue<P,std::vector<P>,std::greater<P> > e;
inline ll MST(int n){int sum=0;F.init(n);while(!e.empty()){P cur=e.top();e.pop();int u=cur.second.first,v=cur.second.second;if(F.f_find(u)==F.f_find(v))continue;else{F.f_push(u,v);sum+=cur.first;}}return sum;}
};
struct PRIM{
#define INF 0x3f3f3f3f
ll dis[N];
bool vis[N];
cb_graph::dis_edge e;
inline void init(int n){FOR(i,2,n) dis[i]=INF;dis[1]=0;FOR(i,1,n)vis[i]=0;}
inline int work(int n){int tot=0,nw=1,ans=0;for(int i=e.frt[1];i;i=e.nxt[i]){dis[e.to[i]]=std::min(dis[e.to[i]],e.dis[i]);}while(++tot<n){int xmin=INF;vis[nw]=1;FOR(i,1,n){if(!vis[i]&&xmin>dis[i]){xmin=dis[i];nw=i;}}if(xmin==INF){return -1;}ans+=xmin;for(int i=e.frt[nw];i;i=e.nxt[i]){int v=e.to[i];if(!vis[v]&&dis[v]>e.dis[i]){dis[v]=e.dis[i];}}}return ans;}
};
}
namespace cb_AstarK{
double eee;
cb_blah::DIJ cb;
struct node{
int x;
double h;
bool operator <(const struct node y)const{double a=h+cb.ds[x],b=y.h+cb.ds[y.x];return a>b;}
};
struct AX{
cb_graph::dis_edge _e;
std::priority_queue<struct node> q;
int cnt=0;
double ans=0;
inline void bfs(int n){node qwq;qwq.x=1;qwq.h=0;q.push(qwq);while(!q.empty()){node cur=q.top();q.pop();int u=cur.x;if(u==n){if(ans+cur.h<=eee){ans+=cur.h;cnt++;}else {break;}}if(cb.ds[u]==0x7f7f7f7f7f7f7f7f) break;for(int i=_e.frt[u];i;i=_e.nxt[i]){node qwe;qwe=cur;qwe.x=_e.to[i];qwe.h+=_e.dis[i];q.push(qwe);}}}
};
}
namespace cb_TA{
ll c[N];
inline int lb(auto x){return (x&(-x));}
inline void add(int x,int w,int n){while(x<=n){c[x]+=w;x+=lb(x);}}
inline ll query(int x){ll res=0;while(x){res+=c[x];x-=lb(x);}return res;}
}
namespace cb_Trie{
struct _01trie{
struct Node{
int ch[2];
int sz;
}tr[N<<4];
int tot=1,rt=1;
inline void push(auto x,int up){int nw=rt;RFOR(i,up,0){bool op=(x>>i)&1;tr[nw].sz++;if(tr[nw].ch[op]) nw=tr[nw].ch[op];else {nw=tr[nw].ch[op]=++tot;}}tr[nw].sz++;}
inline int query(auto x,auto k,int up){int ans=0;int nw=rt;RFOR(i,up,0){bool op=(x>>i)&1;if(tr[nw].ch[!op]){if(k<=tr[tr[nw].ch[!op]].sz){nw=tr[nw].ch[!op];ans|=1ll<<i;}else {k-=tr[tr[nw].ch[!op]].sz;nw=tr[nw].ch[op];}}else {nw=tr[nw].ch[op];}}return ans;}
};
struct _wdtrie{
struct node{
int ch[65],ct,sz;
}a[N];
int tot=1,rt=1;
inline int got(char x){if('A'<=x&&x<='Z') return x-'A';if('a'<=x&&x<='z') return x-'a'+26;if('0'<=x&&x<='9') return x-'0'+52;}
inline void push(std::string s){int l=s.length();int nw=rt;for(int i=0;i<l;i++){int x=got(s[i]);++a[nw].sz;if(a[nw].ch[x]) nw=a[nw].ch[x];else nw=a[nw].ch[x]=++tot;}++a[nw].ct;++a[nw].sz;}
inline int find(std::string s){int nw=rt;int l=s.length();for(int i=0;i<l;i++){int x=got(s[i]);if(!a[nw].ch[x]) return 0;nw=a[nw].ch[x];}return a[nw].sz;}
};
}
namespace cb_LT{
int d[N];
struct node{
int l,r,ds;
ll z;
}tree[N];
int cnt=0;
inline void add(auto x){tree[++cnt].z=x;tree[cnt].ds=1;tree[cnt].l=tree[cnt].r=0;}
inline bool pan(int x,int y){return(tree[x].z==tree[y].z ? x>y : tree[x].z>tree[y].z);}
inline int merge(int x,int y){if(!x||!y) return x^y;if(pan(x,y)) chamber::swep(x,y);tree[x].r=merge(tree[x].r,y);if(tree[tree[x].r].ds>tree[tree[x].l].ds) chamber::swep(tree[x].r,tree[x].l);tree[x].ds=tree[tree[x].r].ds+1;return x;}
}
namespace cb_BNY{
int Rt,Sz,Dmax;
cb_graph::no_dis_edge e;
int dep[N],vis[N],sz[N];
inline void dfs_for_size(int u,int fa){sz[u]=1;for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];if(v==fa||vis[v]) continue;dfs_for_size(v,u);sz[u]+=sz[v];}}
inline void dfs_for_barycenter(int u,int fa){int dmax=Sz-sz[u];for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];if(v==fa||vis[v]) continue;dmax=std::max(dmax,sz[v]);dfs_for_barycenter(v,u);}if(dmax<Dmax){Dmax=dmax;Rt=u;}}
inline void dfsa(int u,int fa){/*统计*/}
inline void dfsb(int u,int fa){/*更新*/}
inline void dfsc(int u,int fa){/*撤销*/}
inline void clac(int u){dep[u]=0;for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];if(vis[v]) continue;/*更新*/dfsa(v,u);dfsb(v,u);}for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];if(vis[v]) continue;dfsc(v,u);}}
inline void bny(int u){dfs_for_size(u,0);Sz=sz[u];Dmax=0x7f7f7f7f;Rt=u;dfs_for_barycenter(u,0);int rt=Rt;vis[rt]=1;clac(rt);for(int i=e.frt[rt];i;i=e.nxt[i]){int v=e.to[i];if(vis[v]) continue;bny(v);}}
}
namespace cb_TJ{
std::vector<int> ans[N];
int tot=0;
cb_STL::STACK st;
cb_graph::no_dis_edge e;
int dfn[N],low[N],num;
inline void bs(int u,int cm){dfn[u]=low[u]=++num;st.push(u);for(int i=e.frt[u];i;i=e.nxt[i]){if(i==(cm^1)) continue;int v=e.to[i];if(!dfn[v]){bs(v,i);low[u]=std::min(low[u],low[v]);}else {low[u]=std::min(low[u],dfn[v]);}}if(low[u]==dfn[u]){++tot;ans[tot].push_back(u);while(st.top()!=u){ans[tot].push_back(st.top());st.pop();}st.pop();}}
inline void ds(int u,int fa){int k=0;dfn[u]=low[u]=++num;st.push(u);for(int i=e.frt[u];i;i=e.nxt[i]){int v=e.to[i];if(v==fa) continue;if(!dfn[v]){++k;ds(v,u);low[u]=std::min(low[u],low[v]);if(low[v]>=dfn[u]){++tot;while(st.top()!=v){ans[tot].push_back(st.top());st.pop();}ans[tot].push_back(v);st.pop();ans[tot].push_back(u);}}else {low[u]=std::min(low[u],dfn[v]);}}if(!fa&&!k){ans[++tot].push_back(u);}}
bool bj[N],rt;
inline void gd(int x){dfn[x]=low[x]=++num;int tot=0;for(int i=e.frt[x];i;i=e.nxt[i]){int v=e.to[i];if(!dfn[v]){gd(v);low[x]=std::min(low[x],low[v]);if(low[v]>=dfn[x]) tot++;}else low[x]=std::min(low[x],dfn[v]);}if(x==rt){if(tot>=2){bj[x]=1;}}else {if(tot>=1){bj[x]=1;}}}
}
namespace cb_Btree{
struct FHQ{
int cnt;
struct node{
int l,r,key;
int sz;
ll val;
}tr[N];
inline void init(){srand(2695);}
inline void update(int u){tr[u].sz=tr[tr[u].l].sz+tr[tr[u].r].sz+1;}
inline void split(int u,int x,int &l,int &r){if(!u){l=r=0;return ;}if(tr[u].val<=x){l=u;split(tr[u].r,x,tr[u].r,r);}else {r=u;split(tr[u].l,x,l,tr[u].l);}update(u);}
inline void add(auto x){tr[++cnt].sz=1;tr[cnt].l=tr[cnt].r=0;tr[cnt].val=x;tr[cnt].key=rand();}
inline int merge(int l,int r){if(!l||!r) return l+r;if(tr[l].key<=tr[r].key){tr[l].r=merge(tr[l].r,r);update(l);return l;}else {tr[r].l=merge(l,tr[r].l);update(r);return r;}}
inline int kth(int u,int k){if(k<=tr[tr[u].l].sz){return kth(tr[u].l,k);}else if(k==tr[tr[u].l].sz+1) return u;else {k-=(tr[tr[u].l].sz+1);return kth(tr[u].r,k);}}
};
struct SPLAY{
int a[N],sz[N],ch[N][2],Fa[N],cnt[N];
int top,root,n;
inline void update(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];}
inline int getwh(int x){return (ch[Fa[x]][0]==x ? 0 : 1);}
inline void rotate(int x){int y=Fa[x],z=Fa[y],k=getwh(x);Fa[x]=z;if(z) ch[z][getwh(y)]=x;ch[y][k]=ch[x][k^1];if(ch[x][k^1]) Fa[ch[x][k^1]]=y;Fa[y]=x;ch[x][k^1]=y;update(y);update(x);}
inline void splay(int x,int tar){while(Fa[x]!=tar){int y=Fa[x],z=Fa[y];if(z!=tar){if(getwh(x)==getwh(y)) rotate(y);else rotate(x);}rotate(x);}if(!tar) root=x;}
inline void find(auto v){int x=root;if(!x) return ;while(ch[x][v>a[x]]&&v!=a[x]){x=ch[x][v>a[x]];}splay(x,0);}
inline void insert(auto v){int x=root,y=0;while(x&&a[x]!=v){y=x;x=ch[x][v>a[x]];}if(x) cnt[x]++;else {x=++top;if(y) ch[y][v>a[y]]=x;ch[x][0]=ch[x][1]=0;Fa[x]=y;a[x]=v;cnt[x]=1;sz[x]=1;}splay(x,0);}
inline int near(int v,int f){find(v);int x=root;if(a[x]>v&&f) return x;if(a[x]<v&&!f) return x;x=ch[x][f];while(ch[x][f^1]) x=ch[x][f^1];return x;}
inline void del(int v){int pre=near(v,0),next=near(v,1);splay(pre,0);splay(next,pre);int tmp=ch[next][0];if(cnt[tmp]>1){cnt[tmp]--;splay(tmp,0);}else {ch[next][0]=0;Fa[tmp]=0;}}
inline int kth(int k){int x=root;if(sz[x]<k) return 0;while(1){int lc=ch[x][0];if(k>sz[lc]+cnt[x]){k-=sz[lc]+cnt[x];x=ch[x][1];}else if(sz[lc]>=k) x=lc;else return a[x];}}
inline int getrank(int v){find(v);return sz[ch[root][0]];}
};
}
namespace cb_jh{
const double pi=2.0*acos(0.0);
struct vector2{
double x,y;
vector2(double x_=0,double y_=0){x=x_;y=y_;}
bool operator == (const vector2& cur) const {return x==cur.x&&y==cur.y;}
bool operator < (const vector2& cur) const {return x!=cur.x ? x<cur.x : y<cur.y;}
vector2 operator + (const vector2& cur) const{return vector2{x+cur.x,y+cur.y};}
vector2 operator - (const vector2& cur) const{return vector2{x-cur.x,y-cur.y};}
vector2 operator * (double cur) const{return vector2{x*cur,y*cur};}
double norm() const {return hypot(x,y);}
vector2 normalize() const{return vector2{x/norm(),y/norm()};}
inline double polar() const{return fmod(atan2(y,x)+2*pi,2*pi);}
inline double dot(const vector2& cur) const{return x*cur.x+y*cur.y;}
inline double cross(const vector2& cur) const{return x*cur.y-cur.x*y;}
inline vector2 project(const vector2& cur) const{vector2 r=cur.normalize();return r*r.dot(*this);}
};
inline double howMuchClose(vector2 p,vector2 a,vector2 b){return (b-p).norm()-(a-p).norm();}
inline double ccw(vector2 a,vector2 b){return a.cross(b);}
inline double ccw(vector2 a,vector2 b,vector2 p){return ccw(a-p,b-p);}
const double eps=1e-19;
inline bool lineIntersection(vector2 a,vector2 b,vector2 c,vector2 d,vector2 &x){double det=(b-a).cross(d-c);if(fabs(det)<eps) return 0;x=a+(b-a)*((c-a).cross(d-c)/det);return 1;}
inline bool parallelSegments(vector2 a,vector2 b,vector2 c,vector2 d,vector2 &p){if(b<a) std::swap(b,a);if(d<c) std::swap(d,c);if(ccw(a,b,c)!=0||b<c||d<c) return 0;if(a<c) p=c;else p=a;return 1;}
inline bool inBoundingRectangle(vector2 p,vector2 a,vector2 b){if(b<a) std::swap(a,b);return p==a||p==b||(a<p&&p<b);}
inline bool segmentInterection(vector2 a,vector2 b,vector2 c,vector2 d,vector2 &p){if(!lineIntersection(a,b,c,d,p)) return parallelSegments(a,b,c,d,p);return inBoundingRectangle(p,a,b)&&inBoundingRectangle(p,c,d);}
inline bool segmentIntersects(vector2 a,vector2 b,vector2 c,vector2 d){double ab=ccw(a,b,c)*ccw(a,b,d);double cd=ccw(c,d,a)*ccw(c,d,b);if(ab==0&&cd==0){if(b<a) std::swap(a,b);if(d<c) std::swap(c,d);return !(b<c||d<a);}return ab<=0&&cd<=0;}
inline vector2 perpendicularFoot(vector2 p,vector2 a,vector2 b){return a+(p-a).project(b-a);}
inline double pointToLine(vector2 p,vector2 a,vector2 b){return (p-perpendicularFoot(p,a,b)).norm();}
typedef std::vector<vector2> polygon;
inline double area(const polygon &p){double res(0);rop(i,0,p.size()){int j=(i+1)%p.size();res+=(p[i].x*p[j].y-p[j].x*p[i].y);}return fabs(res)/2.0;}
inline bool isInside(vector2 q,const polygon &p){int crosses=0;rop(i,0,p.size()){int j=(i+1)%p.size();if((p[i].y>q.y)!=(p[j].y>q.y)){double atX=(p[j].x-p[i].x)*(q.y-p[i].y)/(p[j].y-p[i].y)+p[i].x;if(q.x<atX) ++crosses;}}return crosses%2>0;}
inline polygon giftWarp(const polygon &points){int n=points.size();polygon hull;vector2 pivot=*min_element(points.begin(),points.end());hull.push_back(pivot);while(1){vector2 ph=hull.back(),nxt=points[0];rop(i,1,n){double cross=ccw(ph,nxt,points[i]);double dist=(nxt-ph).norm()-(points[i]-ph).norm();if(cross>0||(cross==0&&dist<0)) nxt=points[i];}if(nxt==pivot) break;hull.push_back(nxt);}return hull;}
inline bool polygonIntersects(const polygon &p,const polygon &q){int n=p.size(),m=q.size();if(isInside(p[0],q)||isInside(q[0],p)) return 1;rop(i,0,n){rop(j,0,m){if(segmentIntersects(p[i],p[(i+1)%n],q[j],q[(j+1)%m])) return 1;}}return 0;}
inline double diameter(const polygon &p){int n=p.size();int left=min_element(p.begin(),p.end())-p.begin();int right=max_element(p.begin(),p.end())-p.begin();vector2 calipersA(0,1);double ret=(p[right]-p[left]).norm();std::vector<vector2> toNext(n);rop(i,0,n){toNext[i]=(p[(i+1)%n]-p[i]).normalize();}int a=left,b=right;while(a!=right||b!=left){double cosThetaA=calipersA.dot(toNext[a]);double cosThetaB=-calipersA.dot(toNext[b]);if(cosThetaA>cosThetaB){calipersA=toNext[a];a=(a+1)%n;}else {calipersA.x=-toNext[b].x;calipersA.y=-toNext[b].y;b=(b+1)%n;}ret=std::max(ret,(p[a]-p[b]).norm());}}
}
const int Q=505;
namespace cb_halfgraph{
int mch[Q],vis[Q];
int edge[Q][Q];
inline bool work(int u,int n){FOR(i,1,n){if(!vis[i]&&edge[u][i]&&(vis[i]=1)){if((!mch[i]||work(mch[i],n))&&(mch[i]=u)) return 1;}}return 0;}
}
using namespace std;
int main(){
// int x,y;
// cin>>x>>y;
// cout<<chamber::gcd(x,y);
return 0;
}
个人缺省源(全,更行ing)
于 2024-10-06 17:03:45 首次发布