若是\(N = M\)node
答案是\(2N!M!\)c++
若是\(|N - M| = 1\)ui
答案是\(N!M!\)spa
不然答案是0code
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int N,M; int fac[MAXN]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } void Solve() { read(N);read(M); if(abs(N - M) > 1) {puts("0");return;} fac[0] = 1; for(int i = 1 ; i <= max(N,M) ; ++i) { fac[i] = mul(fac[i - 1],i); } int ans = mul(fac[N],fac[M]); if(N == M) { ans = mul(ans,2); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
發現橫座標排序和縱座標排序後,只有相鄰的邊會有邊排序
而後跑最小生成樹便可ci
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int N; int x[MAXN],y[MAXN]; int id[MAXN],cnt,fa[MAXN]; struct node { int u,v,c; }E[MAXN * 10]; int getfa(int u) { return fa[u] == u ? u : fa[u] = getfa(fa[u]); } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) {read(x[i]);read(y[i]);} for(int i = 1 ; i <= N ; ++i) id[i] = i; sort(id + 1,id + N + 1,[](int a,int b) {return x[a] < x[b];}); for(int i = 1 ; i < N ; ++i) { E[++cnt] = (node){id[i],id[i + 1],x[id[i + 1]] - x[id[i]]}; } for(int i = 1 ; i <= N ; ++i) id[i] = i; sort(id + 1,id + N + 1,[](int a,int b) {return y[a] < y[b];}); for(int i = 1 ; i < N ; ++i) { E[++cnt] = (node){id[i],id[i + 1],y[id[i + 1]] - y[id[i]]}; } sort(E + 1,E + cnt + 1,[](node a,node b){return a.c < b.c;}); for(int i = 1 ; i <= N ; ++i) fa[i] = i; int ans = 0; for(int i = 1 ; i <= cnt ; ++i) { if(getfa(E[i].u) != getfa(E[i].v)) { ans += E[i].c; fa[getfa(E[i].u)] = getfa(E[i].v); } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
只有兩個點都在邊上的連線纔有影響,咱們把這些點按照順時針(逆時針也能夠)扔進棧裏,棧頂元素和它相同則彈出,若是最後棧是空的就合法,不然就不合法get
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } struct node { int x,y,p; }; int R,C; int N; int x[MAXN][2],y[MAXN][2]; vector<node> v[4]; int sta[MAXN * 2],top; bool on_u(int x,int y) { return x == 0; } bool on_l(int x,int y) { return x != 0 && x != R && y == 0; } bool on_r(int x,int y) { return x != 0 && x != R && y == C; } bool on_d(int x,int y) { return x == R; } bool check(int x,int y) { return on_u(x,y) || on_l(x,y) || on_r(x,y) || on_d(x,y); } int id(int x,int y) { if(on_u(x,y)) return 0; else if(on_r(x,y)) return 1; else if(on_d(x,y)) return 2; else return 3; } void Solve() { read(R);read(C);read(N); for(int i = 1 ; i <= N ; ++i) { for(int j = 0 ; j <= 1 ; ++j) {read(x[i][j]);read(y[i][j]);} if(check(x[i][0],y[i][0]) && check(x[i][1],y[i][1])) { v[id(x[i][0],y[i][0])].pb((node){x[i][0],y[i][0],i}); v[id(x[i][1],y[i][1])].pb((node){x[i][1],y[i][1],i}); } } sort(v[0].begin(),v[0].end(),[](node a,node b){return a.y < b.y;}); sort(v[1].begin(),v[1].end(),[](node a,node b){return a.x < b.x;}); sort(v[2].begin(),v[2].end(),[](node a,node b){return a.y > b.y;}); sort(v[3].begin(),v[3].end(),[](node a,node b){return a.x > b.x;}); for(int i = 0 ; i < 4 ; ++i) { for(auto t : v[i]) { if(sta[top] == t.p) --top; else sta[++top] = t.p; } } if(top) puts("NO"); else puts("YES"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
線段樹維護hall定理,好像以前遇到過相似的可是沒有寫這個作法。。。it
hall定理是什麼呢class
\(X,Y\)爲兩邊的點集,\(X\)和\(Y\)之間存在完美匹配,僅當\(X\)中任意\(k\)個點組成的點集和\(Y\)中的至少$k
$個點相連
這是充分必要的
那麼咱們求的是人數-最大匹配,也就是每一個點集減去匹配\(Y\)點集椅子個數的最大值,初始的答案先設成\(max(N - M,0)\)
設點集大小爲\(|X|\),匹配\(Y\)點集的椅子數是\(\Gamma(X)\)
答案顯然不小於\((|X| - |\Gamma(X)|)_{max}\)
若是答案大於\((|X| - |\Gamma(X)|)_{max}\),設\(t > (|X| - |\Gamma(X)|)_{max}\),若是當前存在一個大於t的未匹配點,那麼選這t個點必定與對面至少一個點相連,設爲\(v\),若v被匹配,找到匹配點u,u與這t個點組成的點集匹配至少兩個點,因此能夠增長一個匹配點,能夠證實答案不大於\((|X| - |\Gamma(X)|)_{max}\)
因此只要考慮怎麼求\((|X| - |\Gamma(X)|)_{max}\)
顯然是對於一個固定的區間,計算多少個點的\(L_{i},R_{i}\)覆蓋了這個區間,因此把區間按左端點排序,而後線段樹維護便可
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,M; struct node { int l,r; }p[MAXN]; struct seg_tree { int l,r; int lz,mx; }tr[MAXN * 4]; void update(int u) { tr[u].mx = max(tr[u << 1 | 1].mx,tr[u << 1].mx); } void addlz(int u,int v) { tr[u].mx += v;tr[u].lz += v; } void pushdown(int u) { if(tr[u].lz) { addlz(u << 1,tr[u].lz); addlz(u << 1 | 1,tr[u].lz); tr[u].lz = 0; } } void build(int u,int l,int r) { tr[u].l = l;tr[u].r = r; if(l == r) { tr[u].mx = r; return; } int mid = (l + r) >> 1; build(u << 1,l,mid); build(u << 1 | 1,mid + 1,r); update(u); } void Change(int u,int l,int r,int v) { if(tr[u].l == l && tr[u].r == r) {addlz(u,v);return;} pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; if(r <= mid) Change(u << 1,l,r,v); else if(l > mid) Change(u << 1 | 1,l,r,v); else {Change(u << 1,l,mid,v);Change(u << 1 | 1,mid + 1,r,v);} update(u); } int Query(int u,int l,int r) { if(tr[u].l == l && tr[u].r == r) {return tr[u].mx;} pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; if(r <= mid) return Query(u << 1,l,r); else if(l > mid) return Query(u << 1 | 1,l,r); else return max(Query(u << 1,l,mid),Query(u << 1 | 1,mid + 1,r)); } void Solve() { read(N);read(M); for(int i = 1 ; i <= N ; ++i) { read(p[i].l);read(p[i].r); } build(1,1,M + 1); sort(p + 1,p + N + 1,[](node a,node b){return a.l < b.l || (a.l == b.l && a.r > b.r);}); int ans = max(0,N - M); for(int i = 1 ; i <= N ; ++i) { Change(1,p[i].l + 1,p[i].r,1); int t = Query(1,p[i].l + 1,M + 1) - M - p[i].l - 1; ans = max(ans,t); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }