本场金牌线为六题前一半,这里提供难度前八题的题解。
本场真是个细节场,银牌金牌题细节都相当地多。
ICPC2023沈阳站
C:
作为签到题,对这种赛制熟悉不熟悉直接区分了一血时间。谔谔。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=501010;
const ll qwq=303030;
const ll inf=0x3f3f3f3f;
ll T;
ll n,m;
int du[N];
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
int main() {
int ans;
n = read(); m = read();
if(n==0 && m==0) ans = 4;
if(n==0 && m==1) ans = 4;
if(n==0 && m==2) ans = 6;
if(n==1 && m==0) ans = 3;
if(n==1 && m==1) ans = 3;
if(n==1 && m==2) ans = 4;
if(n==2 && m==0) ans = 2;
if(n==2 && m==1) ans = 2;
if(n==2 && m==2) ans = 2;
cout<<ans;
return 0;
}
J:
博弈论,看着挺吓人的,但结论很简单。
手玩一会儿后会发现两个关键点:1、u --> v 后,u会变成叶子;2、u --> v 且 v 是一个叶子,那么操作完树的形态是不会改变的,根据题意,我们不允许 v 是叶子。
所以每进行一个操作就会多一个叶子,统计一下非叶结点的奇偶即可。
有个坑点是 n=2,作为签到题,坑罚时用的,很快就能发现。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=501010;
const ll qwq=303030;
const ll inf=0x3f3f3f3f;
ll T;
ll n,m;
int du[N];
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
int main() {
int x,y;
n = read();
for(int i=1;i<n;i++) {
x = read(); y = read();
du[x]++; du[y]++;
}
int ji = 0, you = 0;
for(int i=1;i<=n;i++) {
if(du[i]>1) ji^=1, you = 1;
}
if(!(ji&1) && you) cout<<"Alice";
else cout<<"Bob";
return 0;
}
E:
好经典的题意。农夫,狼,羊,小船,过河。
这题不需要数学结论,根据数据范围容易写出BFS方程,\(dis[x][y][0/1]\) 表示某岸上羊和狼的数量以及农夫现在的位置,每次过河check一下。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=501010;
const ll qwq=303030;
const ll inf=0x3f3f3f3f;
ll T;
int X,Y,Q,P;
struct D{
int di,x,y,cl;
};
queue <D> q;
int dis[111][111][2];
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
inline bool check(int x,int y,int cl) {
if(cl==1) {
return (Y-y)<=((X-x)+P) || x==X;
}
else {
return y<=(x+P) || x==0;
}
}
int main() {
X = read(); Y = read(); Q = read(); P = read();
memset(dis,0x3f,sizeof(dis));
dis[0][0][0] = 0; q.push({0,0,0,0});
while(!q.empty()) {
D now = q.front(); q.pop();
// cout<<now.di<<" : "<<now.x<<" "<<now.y<<" "<<now.cl<<"\n";
if(now.cl==0) {
for(int i=0;i<=X-now.x;i++) {
for(int j=0;j<=Y-now.y;j++) {
if(j+i>Q) break;
if(!check(now.x+i,now.y+j,1)) continue;
// cout<<" i = "<<i<<" j = "<<j<<endl;
if(now.x+i==X) { cout<<now.di+1; return 0; }
if(dis[now.x+i][now.y+j][1] > now.di+1)
q.push({now.di+1,now.x+i,now.y+j,1}), dis[now.x+i][now.y+j][1] = now.di+1;
}
}
}
else {
for(int i=0;i<=now.x;i++) {
for(int j=0;j<=now.y;j++) {
if(j+i>Q) break;
if(!check(now.x-i,now.y-j,0)) continue;
if(dis[now.x-i][now.y-j][0] > now.di+1)
q.push({now.di+1,now.x-i,now.y-j,0}), dis[now.x-i][now.y-j][0] = now.di+1;
}
}
}
}
cout<<-1;
return 0;
}
K:
数据结构好题。
涨分次数最多肯定是涨分场全放前面,假设有 k 个涨分场,我们把涨分多的场放前面,最后一场涨分最小,如果我们把所有的掉分场插到涨分最小的场前面,就有可能得到 k-1,同理 k-2 就是插在倒数第二大的涨分场前面,答案就是搜索掉分场加起来的数值可以覆盖多少加分场。
我撸了棵平衡树,其实权值线段树上二分就行。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
#define ls son[x][0]
#define rs son[x][1]
using namespace std;
const ll N=801010;
const ll qwq=303030;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll Q;
ll n,m,tot;
ll a[N];
ll fu;
ll rt,fa[N],son[N][2],siz[N],num[N],val[N],sum[N];
inline ll read() {
ll sum1 = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum1 = sum1 * 10 + c - '0'; c = getchar(); }
return sum1 * ff;
}
inline ll touhou(ll x) { return son[fa[x]][1]==x; }
inline void pushup(ll x) { siz[x] = siz[ls] + siz[rs] + num[x]; sum[x] = sum[ls] + sum[rs] + num[x] * val[x]; }
inline void rotate(ll x) {
ll y = fa[x], z = fa[y], k = touhou(x), w = son[x][k^1];
son[z][touhou(y)] = x; son[x][k^1] = y; son[y][k] = w;
fa[w] = y; fa[y] = x; fa[x] = z; pushup(y); pushup(x);
}
inline void splay(ll x,ll goal) {
while(fa[x]!=goal) {
ll y = fa[x], z = fa[y];
if(z!=goal) {
if(touhou(y)==touhou(x)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(!goal) rt = x;
}
inline void insert(ll v) {
ll x = rt, f = 0;
while(val[x]!=v && x)
f = x, x = son[x][val[x]<v];
if(x) num[x]++, pushup(x);
else {
x = ++tot;
if(f) son[f][val[f]<v] = x;
fa[x] = f; siz[x] = num[x] = 1;
val[x] = sum[x] = v;
}
splay(x,0);
}
inline void find(ll v) {
ll x = rt;
while(val[x]!=v && son[x][ val[x]<v ])
x = son[x][ val[x]<v ];
splay(x,0);
}
inline ll qian(ll v) {
find(v);
if(val[rt]<v) return rt;
ll x = son[rt][0];
while(rs) x = rs; return x;
}
inline ll hou(ll v) {
find(v);
if(val[rt]>v) return rt;
ll x = son[rt][1];
while(ls) x = ls; return x;
}
void del(ll v) {
ll y = qian(v), x = hou(v);
splay(y,0); splay(x,y);
if(num[ls]>1) num[ls]--, siz[ls]--, sum[ls]-=val[ls];
else ls = 0;
pushup(x); pushup(y);
}
inline ll query(ll v) {
if(!fu) return 0;
ll x = rt;
while(1) {
if(sum[ls]>=v) x = ls;
else if(sum[ls]+val[x]*num[x]<v) v -= sum[ls]+val[x]*num[x], x = rs;
else {v -= sum[ls]; break;}
}
splay(x,0);
ll res = siz[ls]-1;
res += v/val[rt];
return res;
}
int main() {
ll x,wei;
insert(inf); insert(0);
n = read(); Q = read();
for(ll i=1;i<=n;i++) {
a[i] = read();
if(a[i]>0) insert(a[i]);
else fu -= a[i];
}
while(Q--) {
wei = read(); x = read();
if(a[wei]<=0) fu += a[wei];
else del(a[wei]);
if(x<=0) fu -= x;
else insert(x);
a[wei] = x;
// outing();
cout<<query(fu)+1<<"\n";
}
return 0;
}
M:
手玩题。
起始数字不重要,所以我默认从1开始,发现有些无厘头。
其实该从0开始,0才是程序员的浪漫。手玩过后发现两位一循环,一个循环节是 0->1->3->2->0,每多一位就把前面的部分复制 4 遍(要注意纯0只会出现一次)。第 k 次到达 0 的步数是 \(4^1+4^2+4^3+...+4^k\) ,其他的数字,到达次数取决于末尾 0 的个数,设题目所给次数为x,x要小于等于0的个数加一。我们可以把前面 1 的步数计算完,再加上 \(4^1+4^2+...+4^x\)。
细节还挺多,感觉导致这场金牌线题数少的最大元凶就是这题,但是个不错的手玩题。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=2201010;
const ll qwq=303030;
const ll inf=0x3f3f3f3f;
const ll p=1000000007, in3=333333336;
ll T;
ll n,m,k;
char s[N],t[N];
ll a[N],b[N],c[N];
ll ans;
ll f[N];
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
inline ll ksm(ll aa,ll bb) {
ll sum = 1;
while(bb) {
if(bb&1) sum = sum * aa %p;
bb >>= 1; aa = aa * aa %p;
}
return sum;
}
void chushihua() {
ans = 0;
}
inline ll duan(ll i) {
if(i<=N-10) return f[i];
return (ksm(4,i)-1+p) * in3 %p;
}
int main() {
f[1] = 1;
for(int i=1;i<=N-10;i++) f[i] = (f[i-1] * 4ll + 1ll) %p;
T = read();
while(T--) {
chushihua();
scanf("%s%s",s+1,t+1); n = strlen(s+1); m = strlen(t+1);
k = read();
ll len = max(n,m);
if(len&1) len++;
for(ll i=1;i<=len;i++) {
if(i<=n) a[i] = s[n+1-i] - '0'; else a[i] = 0;
if(i<=m) b[i] = t[m+1-i] - '0'; else b[i] = 0;
}
len >>= 1;
int you = 0;
for(ll i=1;i<=len;i++) {
int yi = a[(i<<1)-1] ^ b[(i<<1)-1];
int er = a[i<<1] ^ b[i<<1];
if(yi && er) c[i] = 2;
if(yi && !er) c[i] = 1;
if(!yi && er) c[i] = 3;
if(!yi && !er) c[i] = 0;
if(c[i] && !you) you = i;
}
if(!you) {
cout<<(duan(k)-1+p)%p<<"\n";
continue;
}
if(k>you) { cout<<"-1\n"; continue; }
c[k-1] = 4;
for(ll i=1;i<=len;i++) {
(ans += c[i] * duan(i) %p) %= p;
}
cout<<(ans%p+p)%p<<"\n";
}
return 0;
}
B:
金牌题一。
这题我做过一个简化版本,出题人应该就是根据那一道题改编的。
简化版的那道题是求数字一上一下的排列数量,可以 n^2 dp 解决,\(f[i][j]\) 表示填写到第 i 个数字,第 i 个数字在前面这些数字中排名第 j,在转移时我们不考虑每个数字的绝对数值,而是考虑它们的相对数值,也就是枚举下一个数字插在哪个位置。
这题数据范围很友好,n^4 甚至 n^5 都能过,为了求字典序第 k 大,我们就从第一位填1开始,每次计算下剩余数位有多少方案,每一位扫一遍,n^2可以扫完。怎么统计剩余数位的方案呢,我们把数值看成横轴,位置看成纵轴,我们已经确定了前几个位置的数值,那么横轴上留下一些剩余数值供我们填写,这些数值就构成一上一下的关系,我们用我们上面的思路可以轻松地求出。
思路比较流程,但是细节比较多,比如横轴上留下数值的位置也是有限制的,建议自己手玩一下。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=201010;
const ll qwq=303030;
const ll inf=1e18;
const ll p=1000000007, in3=333333336;
ll n,K;
ll f[111][111];
ll dp[111][111];
ll da = 50;
ll yi;
ll ans[111], a[111];
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
void qiu() {
for(int i=0;i<=da;i++) f[i][0] = 1;
for(int i=0;i<=da;i++) {
memset(dp,0,sizeof(dp));
for(int k=1;k<=i+1;k++) dp[1][k] = 1;
f[i][1] = i+1;
for(int j=2;j<=da;j++) {
if(j&1) {
for(int k=2;k<=i+j;k++) {
for(int l=1;l<=k-1;l++) {
dp[j][k] += dp[j-1][l];
if(dp[j][k] > inf) { dp[j][k] = inf; break; }
}
}
}
else {
for(int k=1;k<i+j;k++) {
for(int l=k;l<i+j;l++) {
dp[j][k] += dp[j-1][l];
if(dp[j][k] > inf) { dp[j][k] = inf; break; }
}
}
}
for(int k=1;k<=i+j;k++) {
f[i][j] += dp[j][k];
if(f[i][j] > inf) { f[i][j] = inf; break; }
}
}
}
}
ll check() {
ll res = 1;
ll len = 0, sum = 0;
for(int j=1;j<=n;j++) {
if(!a[j]) len++;
if(j==n || a[j+1]) {
if(inf / res < f[sum][len]) { res = inf; break; }
res *= f[sum][len];
sum += len;
len = 0;
}
}
return res;
}
int main() {
qiu();
n = read(); K = read();
ll now = 0;
for(int j=1;j<=n;j++) {
if((K - now - 1) / f[0][j-1] < f[j-1][n-j]) { yi = j; break; }
now += f[0][j-1] * f[j-1][n-j];
}
if(!yi) { cout<<-1; return 0; }
ans[1] = yi;
a[yi] = 1;
for(int i=2;i<=n;i++) {
for(int j=1;j<=n;j++) {
bool ke = 0;
if(j==1 && a[2]) ke = 1;
if(j==n && a[n-1]) ke = 1;
if(a[j-1] && a[j+1]) ke = 1;
if((j&1) == (yi&1)) ke = 1;
if(a[j]) ke = 0;
if(!ke) continue;
a[j] = i;
if(now + check() >= K) { ans[i] = j; break; }
now += check();
a[j] = 0;
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}
D:
金牌题二。
S中选一段字符串,T中选一段字符串,拼起来要求是一个平方串。
数据范围是 n^2,于是开始思考各种枚举,我们设 S 中选出的串为 ABA 的形式,T中选出串为 B 的形式(T长则反过来再计算一次就行)。
我们 n^2 的枚举位置,一个是第一个 A 的左端 \(l1\),一个是第二个 A 的左端 \(l2\),这两个位置的后缀串的LCP,决定了 B 串的最小要求长度。统计有多少满足的 B 串可以先 n^2 预处理 S 中每一个位置和 T 中每一个位置的 LCS(在S的每个位置上记录各个LCS数值的出现次数),统计答案就用 \(l2\) 这个位置记录的数据,计算大于 B 串最小长度要求的串的贡献和(经典的两个前缀和统计三角面积)。
感觉,还是有很多细节。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=201010;
const ll qwq=303030;
ll n,m;
char s[5050],t[5050],z[5050];
int f[5050][5050],g[5050][5050];
ll a[5050],b[5050];
ll ans;
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
void solve(ll cl) {
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(ll i=n;i>=1;i--) {
for(ll j=n;j>=1;j--) {
if(s[i]==s[j]) f[i][j] = f[i+1][j+1] + 1;
}
}
for(ll i=1;i<=n;i++) {
for(ll j=1;j<=m;j++) {
if(s[i]==t[j]) g[i][j] = g[i-1][j-1] + 1;
}
}
for(ll i=1;i<=n;i++) {
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(ll j=1;j<=m;j++) {
a[ g[i][j] ]++;
b[ g[i][j] ]+=g[i][j];
}
for(ll j=m;j>=1;j--) a[j] += a[j+1], b[j] += b[j+1];
for(ll j=1;j<=i;j++) {
ll wo = f[i+1][j];
ll zong = (i-j+1);
ll L = max(1ll,zong-wo), R = (cl==1) ? zong : zong-1;
if(L>R) continue;
ans += a[R+1] * (R-L+1);
ans += (b[L] - b[R+1]) - (a[L] - a[R+1]) * (L-1);
}
}
}
int main() {
scanf("%s%s",s+1,t+1); n = strlen(s+1); m = strlen(t+1);
solve(1);
reverse(s+1,s+n+1);
reverse(t+1,t+m+1);
for(ll i=1;i<=n;i++) z[i] = s[i];
for(ll i=1;i<=m;i++) s[i] = t[i];
for(ll i=1;i<=n;i++) t[i] = z[i];
swap(m,n);
solve(0);
cout<<ans;
return 0;
}
I:
金牌题三。
其实不是很难,分类讨论也不是说逆天地多,这题能成为金牌题和榜歪有一定的关系。
首先这题一个很关键的点:肯定有一个矩形能够覆盖两个角。然后这题就能顺利进行下去了。
讨论时我们默认覆盖行的矩形比覆盖列的矩形多,否则swap所有数据,可以少一半的码量。
然后是讨论:
1、有三个覆盖行的矩形:就类似于三个横扛上下滑动。因为要覆盖四个角所以至少有两个横杠是需要固定在角上的,所以就只有一个横杠能上下滑(注意有三个杠都跑到角落的情况,需要容斥)。这个其实是最复杂最难算的情况。
2、有两个覆盖行的矩形:两个横杠上下滑,一个需要固定在上面,一个需要固定在下面。如果中间还有缝隙的话,剩余一个没有覆盖行的矩形肯定是做不到的;如果中间没有缝隙,剩余一个矩形位置随意。
3、一个覆盖行的矩形,一个覆盖列的矩形:无论它俩滑到上下左右的任意位置,留下的空都是固定的,而且留下了一个角导致剩余的矩形位置也固定了,答案不是0就是4。
4、一个覆盖行的矩形:除了这个杠需要覆盖两个角以外,剩下的两个矩形也需要各覆盖一个角,答案不是0就是4。
5、没有覆盖行或列的矩形:答案是0。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define FOR() ll le=e[u].size();for(ll i=0;i<le;i++)
#define QWQ cout<<"QwQ\n";
#define ll long long
#include <vector>
#include <queue>
#include <map>
using namespace std;
const ll N=201010;
const ll qwq=303030;
const ll p=1000000007;
ll T;
ll n,m,H,W;
ll a1,b1,a2,b2,a3,b3;
inline ll read() {
ll sum = 0, ff = 1; char c = getchar();
while(c<'0' || c>'9') { if(c=='-') ff = -1; c = getchar(); }
while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }
return sum * ff;
}
void solve1() {
if(a1*b1==n*m) cout<<(n-a2+1) * (m-b2+1) %p * (n-a3+1) %p * (m-b3+1) %p<<"\n";
else if(a2*b2==n*m) cout<<(n-a1+1) * (m-b1+1) %p * (n-a3+1) %p * (m-b3+1) %p<<"\n";
else if(a3*b3==n*m) cout<<(n-a1+1) * (m-b1+1) %p * (n-a2+1) %p * (m-b2+1) %p<<"\n";
}
void solve2() {
if(W==3) { swap(n,m); swap(a1,b1); swap(a2,b2); swap(a3,b3); }
ll res = 0;
if(b1+b2+b3<m) { cout<<"0\n"; return ; }
if(b1+max(b2,b3)>=m) res += 2;
if(b2+max(b1,b3)>=m) res += 2;
if(b3+max(b1,b2)>=m) res += 2;
if(b1+b2>=m) res += 2 * (m-b3-1);
else {
ll L = max(2ll,m-b2-b3+1);
ll R = min(m-b3,b1+1);
if(L<=R) res += 2 * (R-L+1);
}
if(b1+b3>=m) res += 2 * (m-b2-1);
else {
ll L = max(2ll,m-b3-b2+1);
ll R = min(m-b2,b1+1);
if(L<=R) res += 2 * (R-L+1);
}
if(b2+b3>=m) res += 2 * (m-b1-1);
else {
ll L = max(2ll,m-b3-b1+1);
ll R = min(m-b1,b2+1);
if(L<=R) res += 2 * (R-L+1);
}
cout<<(res%p+p)%p<<"\n";
}
void solve3() {
if(W==2) { swap(n,m); swap(a1,b1); swap(a2,b2); swap(a3,b3); }
ll A, B, C, D;
if(a3!=n) A = b1, B = b2, C = a3, D = b3;
if(a2!=n) A = b1, B = b3, C = a2, D = b2;
if(a1!=n) A = b2, B = b3, C = a1, D = b1;
if(A+B<m) { cout<<"0\n"; return ; }
cout<<2*(n-C+1)%p*(m-D+1)%p<<"\n";
}
void solve4() {
if((a1+a2+a3>=2*n) && (b1+b2+b3>=2*m)) cout<<"4\n";
else cout<<"0\n";
}
void solve5() {
if(W==1) { swap(n,m); swap(a1,b1); swap(a2,b2); swap(a3,b3); }
if(a2==n) swap(a1,a2), swap(b1,b2);
if(a3==n) swap(a1,a3), swap(b1,b3);
if(b1+b2<m || b1+b3<m) { cout<<"0\n"; return ; }
if(a2+a3<n) { cout<<"0\n"; return ; }
cout<<"4\n";
}
int main() {
T = read();
while(T--) {
n = read(); m = read();
a1 = read(); b1 = read(); a2 = read(); b2 = read(); a3 = read(); b3 = read();
if(a1*b1==n*m || a2*b2==n*m || a3*b3==n*m) { solve1(); continue; }
H = W = 0;
if(a1==n) H++; if(a2==n) H++; if(a3==n) H++;
if(b1==m) W++; if(b2==m) W++; if(b3==m) W++;
if(!H && !W) { cout<<"0\n"; continue; }
if(H==3 || W==3) { solve2(); continue; }
if(H==2 || W==2) { solve3(); continue; }
if(H==1 && W==1) { solve4(); continue; }
if(H+W==1) { solve5(); continue; }
}
return 0;
}
标签:ICPC2023,now,沈阳站,const,ll,while,include,getchar
From: https://www.cnblogs.com/maple276/p/18144780