NOI2023春测题解更好的阅读体验戳此进入游记戳此进入T1 LG-P9117 [春季测试 2023] 涂色游戏题面SolutionCodeT2 LG-P9118 [春季测试 2023] 幂次题面SolutionCodeT3 LG-P9119 [春季测试 2023] 圣诞树题面SolutionCodeT4 LG-P9120 [春季测试 2023] 密码锁UPD
给定矩阵,多次操作整行推平或整列推平,最后查询整个矩形。
给每行每列维护一个最后的推平并标记时间戳,查询时取行列最晚的推平作为答案即可。
考虑如果行列的区间推平以及随时查询并且强制在线,可以考虑对每行每列共
xxxxxxxxxx
601
2
3
4
5
6
7
8
9
10
11
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()
然后取其返回值一段较小的邻域进行验证,一般
xxxxxxxxxx
721
2
3
4
5
6
7
8
9
10
11
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 类似,即:
xxxxxxxxxx
971
2
3
4
5
6
7
8
9
10
11
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 初稿