NOI2023春测题解更好的阅读体验戳此进入游记戳此进入T1 LG-P9117 [春季测试 2023] 涂色游戏题面SolutionCodeT2 LG-P9118 [春季测试 2023] 幂次题面SolutionCodeT3 LG-P9119 [春季测试 2023] 圣诞树题面SolutionCodeT4 LG-P9120 [春季测试 2023] 密码锁UPD
给定矩阵,多次操作整行推平或整列推平,最后查询整个矩形。
给每行每列维护一个最后的推平并标记时间戳,查询时取行列最晚的推平作为答案即可。
考虑如果行列的区间推平以及随时查询并且强制在线,可以考虑对每行每列共
xxxxxxxxxx60123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23template < typename T = int >24inline T read(void);25
26int N, M, Q;27pair < int, int > lstx[110000], lsty[110000];28
29int main(){30 int T = read();31 while(T--){32 memset(lstx, 0, sizeof lstx), memset(lsty, 0, sizeof lsty);33 N = read(), M = read(), Q = read();34 for(int i = 1; i <= Q; ++i){35 int opt = read(), p = read(), v = read();36 if(opt == 0)lstx[p] = {v, i};37 else lsty[p] = {v, i};38 }39 for(int i = 1; i <= N; ++i)40 for(int j = 1; j <= M; ++j)41 printf("%d%c", lstx[i].second > lsty[j].second ? lstx[i].first : lsty[j].first, j == M ? '\n' : ' ');42 }43 return 0;44}45
46template < typename T >47inline T read(void){48 T ret(0);49 int flag(1);50 char c = getchar();51 while(c != '-' && !isdigit(c))c = getchar();52 if(c == '-')flag = -1, c = getchar();53 while(isdigit(c)){54 ret *= 10;55 ret += int(c - '0');56 c = getchar();57 }58 ret *= flag;59 return ret;60}给定
感觉差不多是绿题的难度,不卡精度的话应该算黄题难度,赛时的阴间思路在游记里了,这里说一下正解。
不难发现对于任意的合法的 unordered_set 里,最后直接输出其 size() 即可,考虑这样的复杂度,显然枚举
考虑对于 unordered_set 中的所有数,若其为完全平方数的话贡献
同时不难发现对于 double 的 sqrt() 函数的话会丢失精度,所以此时需考虑使用二分或 long double 或 __float128,前者会多一个 __float128 会多一个十分巨大的甚至高于 sqrt() 然后取其返回值一段较小的邻域进行验证,一般
xxxxxxxxxx72123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23template < typename T = int >24inline T read(void);25
26ll N, K;27unordered_set < ll > legal;28ll ans(0);29
30int main(){31 auto qpow_with_lim = [](ll a, ll b)->ll{32 ll ret(1), mul(a);33 while(b){34 if(b & 1)35 ret = (__int128_t)ret * mul > N ? N + 1 : ret * mul;36 b >>= 1;37 mul = (__int128_t)mul * mul > N ? N + 1 : mul * mul;38 }return ret;39 };40
41 N = read < ll >(), K = read();42 if(K == 1)printf("%lld\n", N), exit(0);43 legal.insert(1);44 for(ll i = 2; i <= (ll)1e6; ++i){45 auto cur = (__int128_t)qpow_with_lim(i, K == 2 ? 3 : K);46 while(cur <= N)47 legal.insert(cur), cur *= i;48 }ans += legal.size();49 if(K == 2){50 for(auto v : legal)51 if((ll)sqrt((ld)v) * (ll)sqrt((ld)v) == v)--ans;52 ans += (ll)floor(sqrt((ld)N));53 }printf("%lld\n", ans);54 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);55 return 0;56}57
58template < typename T >59inline T read(void){60 T ret(0);61 int flag(1);62 char c = getchar();63 while(c != '-' && !isdigit(c))c = getchar();64 if(c == '-')flag = -1, c = getchar();65 while(isdigit(c)){66 ret *= 10;67 ret += int(c - '0');68 c = getchar();69 }70 ret *= flag;71 return ret;72}给定平面内凸包,最小化从其最高点开始的任意哈密尔顿路径(认为任意两点之间均可到达)的欧几里得距离,输出最小化的方案。存在 SPJ。
首先对于
考虑正解,发现对于任意两条路径一定不相交,证明是显然的,考虑任意四个点:

显然由于三角形两边之和大于第三边,前者一定优于后者。
所以对于逆时针给定的若干个点,当处于
于是此时问题显然地转化为了区间 DP,考虑将原序列倍长,设状态
转移也十分显然,与 [ABC273F] Hammer 2 类似,即:
xxxxxxxxxx97123
4567891011
12using namespace std;13
14mt19937 rnd(random_device{}());15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}16bool rnddd(int x){return rndd(1, 100) <= x;}17
18typedef unsigned int uint;19typedef unsigned long long unll;20typedef long long ll;21typedef long double ld;22
23template < typename T = int >24inline T read(void);25
26int N;27pair < ld, ld > pts[2100];28ld dis[2100][2100];29ld dp[2100][2100][2];30tuple < int, int, int > frm[2100][2100][2];31int top(-1); ld topy(-1e8);32
33int main(){34 auto CalDis = [](pair < ld, ld > a, pair < ld, ld > b)->ld{35 return sqrt((a.first - b.first) * (a.first - b.first) + (a.second - b.second) * (a.second - b.second));36 };37 auto Update = [](int l, int r, int k, int sl, int sr, int sk, int dl, int dr)->void{38 if(dp[sl][sr][sk] >= 1e12)return;39 if(dp[sl][sr][sk] + dis[dl][dr] < dp[l][r][k])40 dp[l][r][k] = dp[sl][sr][sk] + dis[dl][dr], frm[l][r][k] = {sl, sr, sk};41 };42
43 for(int i = 0; i <= 2010; ++i)for(int j = 0; j <= 2010; ++j)for(int k = 0; k <= 1; ++k)dp[i][j][k] = 1e12;44 N = read();45 for(int i = 1; i <= N; ++i){46 scanf("%Lf%Lf", &pts[i].first, &pts[i].second);47 pts[i + N] = pts[i];48 if(pts[i].second > topy)topy = pts[i].second, top = i;49 }50 for(int i = 1; i <= N; ++i)for(int j = 1; j <= N; ++j)51 dis[i][j] = dis[i + N][j] = dis[i][j + N] = dis[i + N][j + N] = CalDis(pts[i], pts[j]);52 dp[top][top][0] = dp[top][top][1] = dp[top + N][top + N][0] = dp[top + N][top + N][1] = 0.0;53 for(int len = 2; len <= N; ++len)54 for(int l = 1; l <= (N << 1) - len + 1; ++l){55 int r = l + len - 1;56 Update(l, r, 0, l + 1, r, 0, l + 1, l);57 Update(l, r, 0, l + 1, r, 1, r, l);58 Update(l, r, 1, l, r - 1, 0, l, r);59 Update(l, r, 1, l, r - 1, 1, r - 1, r);60 }61 ld ansv(1e12); tuple < int, int, int > curp(0, 0, 0);62 for(int l = 1; l < N; ++l){63 int r = l + N - 1;64 if(dp[l][r][0] < ansv)ansv = dp[l][r][0], curp = {l, r, 0};65 if(dp[l][r][1] < ansv)ansv = dp[l][r][1], curp = {l, r, 1};66 }67 basic_string < int > rans;68 auto [l, r, k] = curp;69 auto lst = curp; curp = frm[l][r][k];70 while(get < 0 >(curp)){71 auto [l, r, k] = lst;72 auto [cl, cr, ck] = curp;73 if(l != cl)rans += l;74 else rans += r;75 lst = curp;76 curp = frm[cl][cr][ck];77 }rans += get < 0 >(lst);78 for_each(rans.rbegin(), rans.rend(), [rans](auto val)->void{printf("%d%c", val > N ? val - N : val, val == *prev(rans.rend()) ? '\n' : ' ');});79 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);80 return 0;81}82
83template < typename T >84inline T read(void){85 T ret(0);86 int flag(1);87 char c = getchar();88 while(c != '-' && !isdigit(c))c = getchar();89 if(c == '-')flag = -1, c = getchar();90 while(isdigit(c)){91 ret *= 10;92 ret += int(c - '0');93 c = getchar();94 }95 ret *= flag;96 return ret;97}update-2023_03_06 初稿