2022.9.5———HZOI【CSP-S开小灶1】游寄
-
\(Write\ In\ Front\)
\(NOI\)赛制中间转成了\(IOI\)赛制,然后就出了点\(bug\),排名之类的也就出了点问题,所以成绩就不挂了
T1 ZZH的游戏,T2 ZZH与背包
\(\mathfrak{T1}\ ZZH的游戏\)
朴素的思路是二分答案\(ans\),然后验证能否达成
然而会\(T\)掉
考虑去掉这个二分,初始final_ans = s+t
,然后就当前局势向外尝试拓展,一直拓展到不能拓展为止。如果此时两棵树没有都到达节点\(1\),那么就让ans ++
,否则退出就行了
代码注释比较多建议粘到本地删掉注释再看
还有一个问题就是可能我写的比较谔谔导致仍然会\(T\),所以就加了个火车头,然后交了也就几十发\(...\)
T1
%:pragma GCC target("avx")
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
%:pragma GCC optimize("-fgcse")
%:pragma GCC optimize("-fgcse-lm")
%:pragma GCC optimize("-fipa-sra")
%:pragma GCC optimize("-ftree-pre")
%:pragma GCC optimize("-ftree-vrp")
%:pragma GCC optimize("-fpeephole2")
%:pragma GCC optimize("-ffast-math")
%:pragma GCC optimize("-fsched-spec")
%:pragma GCC optimize("unroll-loops")
%:pragma GCC optimize("-falign-jumps")
%:pragma GCC optimize("-falign-loops")
%:pragma GCC optimize("-falign-labels")
%:pragma GCC optimize("-fdevirtualize")
%:pragma GCC optimize("-fcaller-saves")
%:pragma GCC optimize("-fcrossjumping")
%:pragma GCC optimize("-fthread-jumps")
%:pragma GCC optimize("-funroll-loops")
%:pragma GCC optimize("-fwhole-program")
%:pragma GCC optimize("-freorder-blocks")
%:pragma GCC optimize("-fschedule-insns")
%:pragma GCC optimize("inline-functions")
%:pragma GCC optimize("-ftree-tail-merge")
%:pragma GCC optimize("-fschedule-insns2")
%:pragma GCC optimize("-fstrict-aliasing")
%:pragma GCC optimize("-fstrict-overflow")
%:pragma GCC optimize("-falign-functions")
%:pragma GCC optimize("-fcse-skip-blocks")
%:pragma GCC optimize("-fcse-follow-jumps")
%:pragma GCC optimize("-fsched-interblock")
%:pragma GCC optimize("-fpartial-inlining")
%:pragma GCC optimize("no-stack-protector")
%:pragma GCC optimize("-freorder-functions")
%:pragma GCC optimize("-findirect-inlining")
%:pragma GCC optimize("-fhoist-adjacent-loads")
%:pragma GCC optimize("-frerun-cse-after-loop")
%:pragma GCC optimize("inline-small-functions")
%:pragma GCC optimize("-finline-small-functions")
%:pragma GCC optimize("-ftree-switch-conversion")
%:pragma GCC optimize("-foptimize-sibling-calls")
%:pragma GCC optimize("-fexpensive-optimizations")
%:pragma GCC optimize("-funsafe-loop-optimizations")
%:pragma GCC optimize("inline-functions-called-once")
%:pragma GCC optimize("-fdelete-null-pointer-checks")
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define re register int
#define char_phi signed
#define MARK cout << "###"
#define MARKER "@@@"
#define LMARK "!!!~~~"
#define ZY " qwq "
#define _ ' '
#define Endl cout << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 1000005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL), cerr.tie(NULL);}
/*
瞄了一眼题解
看起来很可做的样子
限制一个x
就是寻找当前能到的点的最小点,然后跑过去
二分
似乎是可以
nlogn应该能过吧??
哦不。还挂了一个T
哦不。那个n是sigma{n}
哦不。二分多log确实不行。
可以不用二分..
比如..
随机化
我先打打试试
不对啊,sigma{n}是1e6咋就不行了
算了先不管那个先打出来试试
现在四点了
调了两个小时
算是把大样例过了
25分
咋给这么点啊。。
来写线性的
*/
int T, n, s1, s2, mx, mn1, mn2, final_ans, MAXER, lst1, lst2;
long long tim;
double lmt;
char vis1[N], vis2[N];
vector<int> a[N], b[N];
priority_queue<int, vector<int>, greater<int> > q1;
priority_queue<int, vector<int>, greater<int> > q2;
#define insert push
inline char bfs1(int maxer){
int chief; char can(false);
while (q1.empty() == false){
chief = q1.top();
if (chief > maxer)
break;
q1.pop(); vis1[chief] = true, mn1 = MIN(mn1, chief); can = true;
for (re i = 0 ; i < a[chief].size() ; ++ i){
if (vis1[a[chief][i]] == true)
continue;
q1.insert(a[chief][i]);
}
}
return can;
}
inline char bfs2(int maxer){
int chief; char can(false);
while (q2.empty() == false){
chief = q2.top();
if (chief > maxer)
break;
// cout << chief << '\n';
q2.pop(); vis2[chief] = true, mn2 = MIN(mn2, chief); can = true;
for (re i = 0 ; i < b[chief].size() ; ++ i){
if (vis2[b[chief][i]] == true)
continue;
q2.insert(b[chief][i]);
}
}
return can;
}
inline void check(){
memset(vis1, false, sizeof(vis1)), memset(vis2, false, sizeof(vis2));
while (q1.empty() == false)
q1.pop();
while (q2.empty() == false)
q2.pop();
mn1 = lst1 = s1, mn2 = lst2 = s2;
char can1(true), can2(true), fl(false);
q1.insert(s1); vis1[s1] = true;
q2.insert(s2); vis2[s2] = true;
while (true){
can1 = can2 = true;
while (can1 == true or can2 == true){
lst1 = mn1, lst2 = mn2;
can1 = bfs1(final_ans-mn2);
// cerr << "Ive been there." << '\n';
// if (mid == 13)
// cerr << mn1 << _ << mn2 << '\n';
can2 = bfs2(final_ans-mn1);
if (mn1 == 1 and mn2 == 1)
{return ;}
}
// cerr << final_ans << '\n';
final_ans ++;
/*checker:{// 如果能保存历史版本的话可以达到时间复杂度减至二分之一甚至减至四分之一八分之一。。。但是可能保存历史版本也要时间dsu
final_ans --;// ans+=1
can1 = can2 = true; mn1 = lst1, mn2 = lst2;
while (can1 == true or can2 == true){
can1 = bfs1(final_ans-mn2);
// cerr << "Ive been there." << '\n';
// if (mid == 13)
// cerr << mn1 << _ << mn2 << '\n';
can2 = bfs2(final_ans-mn1);
if (mn1 == 1 and mn2 == 1)
{return ;}
}
final_ans ++;// ans+=2
return ;
}*/
}
// return false;
}
inline void Clean(){
mx = 0; final_ans = 1145141919;
for (re i = 1 ; i <= n ; ++ i)
a[i].clear(), b[i].clear();
}
/*调试用珍贵数据
1
10
8 3
7 8
8 9
6 3
5 4
8 4
1 2
2 10
8 1
10 1
10 9
7 3
6 1
9 3
6 5
2 7
9 8
7 4
4 8
ans:13
*/
void work(){
Clean();
cin >> n;
int l, r(0), mid;
for (re i = 1, uu, vv ; i <= n-1 ; ++ i)
{cin >> uu >> vv; a[uu].push_back(vv), a[vv].push_back(uu); mx = MAX(mx, MAX(uu, vv));}
for (re i = 1, uu, vv ; i <= n-1 ; ++ i)
{cin >> uu >> vv; b[uu].push_back(vv), b[vv].push_back(uu); r = MAX(r, MAX(mx+uu, mx+vv));}
cin >> s1 >> s2;
final_ans = s1+s2;
check();
cout << final_ans << '\n';;
// final_ans += n;
// if (T == 0)
// cerr << final_ans << '\n';
// return ;
// l = s1+s2;// r = 1145141919;
// while (l <= r){
// while (true){
// mid = ((l+r) >> 1);
// mid = (rand() % MAXER) + 1;
// cerr << l << _ << r << _ << mid << _ << final_ans << _ << _ << _;
// if (check(mid) == true)
// r = mid-1, final_ans = MIN(final_ans, mid);// , cerr << "Yes" << _ << _;
// else
// l = mid+1;
// if (((clock()-tim) * 1000.0 / CLOCKS_PER_SEC) > lmt)
// break;
// cerr << ((clock()-tim) * 1000.0 / CLOCKS_PER_SEC) << '\n';
// cerr << '\n'; cerr << '\n' << '\n'; cout << '\n' << '\n' << '\n';
// }
// }
// cerr << l << _ << r << _ << mid << _ << final_ans << '\n';
// cout << mid << '\n';
// cerr << '\n' << '\n' << '\n';
// cout << final_ans << '\n';
}
// #define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(a);
#endif
Fastio_setup();
cin >> T;
while (T --)
work();
return GMY;
}
\(\mathfrak{T2}\ ZZH与背包\)
这个题就是个折半搜索的板子题,真的很板
不会折半搜索的可以去学一学,是真的简单
(在另一场比赛考了一个更板的板子然后全场就我一个人写的记搜我才意识到我得学学这玩意)
代码不放了,我也没写
$$\huge{\mathcal{Here\ We\ Are,\ Nick\ Of\ Time\ !}}$$