正睿20NOIp前冲刺day15
估分:100+60+30+20=210
实际:100+60+20+0=180
T1:
打表找规律就行了
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 inline int read() 8 { 9 int x = 0, f = 0; 10 char ch = getchar(); 11 while (!isdigit(ch)) f = ch == '-', ch = getchar(); 12 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 13 return f ? -x : x; 14 } 15 16 int main() 17 { 18 int n = read(), k = read(); 19 if (n % 2 == 0 && k == 1) puts("yrrebxaw"); 20 else puts("qjd"); 21 return 0; 22 }
T2:
60pts的暴力
离线操作,连边删边的时间看作是这条边存在的时间区间,把他放进线段树里,之后查询线段树分治,并查集因为要支持撤销所以只能按秩合并
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<map> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 9 #define id(x,y) 1ll*(x-1)*n+y 10 11 typedef long long LL; 12 13 const int N = 100010; 14 int mod = 1e9 + 7; 15 16 int n, m; 17 int opt[N], x[N], y[N]; 18 int fa[N], sz[N], inv[N], ans = 1; 19 20 vector<pair<int, int> > a[N << 2], v[N << 2]; 21 map<LL, int> k; 22 23 int find(int x) { return x == fa[x] ? fa[x] : find(fa[x]); } 24 25 void merge(int p, int x, int y) 26 { 27 x = find(x), y = find(y); 28 if (x != y) 29 { 30 if (sz[x] < sz[y]) swap(x, y); 31 ans = 1ll * ans * (1ll * inv[sz[x]] * inv[sz[y]] % mod) % mod * (sz[x] + sz[y]) % mod; 32 fa[y] = x, sz[x] += sz[y], v[p].push_back(make_pair(x, y)); 33 } 34 } 35 36 void Delete(int x, int y) 37 { 38 sz[x] -= sz[y]; 39 ans = 1ll * ans * inv[sz[x] + sz[y]] % mod * (1ll * sz[x] * sz[y] % mod) % mod; 40 fa[y] = y; 41 } 42 43 void modify(int p, int l, int r, int lx, int rx, int u, int v) 44 { 45 if (l >= lx && r <= rx) 46 { 47 a[p].push_back(make_pair(u, v)); 48 return; 49 } 50 51 int mid = (l + r) / 2; 52 if (lx <= mid) modify(p << 1, l, mid, lx, rx, u, v); 53 if (rx > mid) modify(p << 1 | 1, mid + 1, r, lx, rx, u, v); 54 } 55 56 void solve(int p, int l, int r) 57 { 58 for (int i = 0; i < (int)a[p].size(); i++) merge(p, a[p][i].first, a[p][i].second); 59 int mid = (l + r) / 2; 60 if (l == r) printf("%d\n", ans); 61 else solve(p << 1, l, mid), solve(p << 1 | 1, mid + 1, r); 62 for (int i = v[p].size() - 1; i >= 0; i--) Delete(v[p][i].first, v[p][i].second); 63 } 64 65 signed main() 66 { 67 scanf("%d%d", &n, &m); 68 inv[1] = 1; 69 for (int i = 2; i <= 1e5; i++) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod; 70 for (int i = 1; i <= n; i++) fa[i] = i, sz[i] = 1; 71 72 for (int i = 1; i <= m; i++) 73 { 74 scanf("%d%d%d", &opt[i], &x[i], &y[i]); 75 if (opt[i] == 1) k[id(x[i], y[i])] = i; 76 else modify(1, 1, m, k[id(x[i], y[i])], i - 1, x[i], y[i]), k[id(x[i], y[i])] = 0; 77 } 78 79 for (int i = 1; i <= m; i++) 80 { 81 if (k[id(x[i], y[i])]) 82 { 83 modify(1, 1, m, k[id(x[i], y[i])], m, x[i], y[i]); 84 } 85 } 86 87 solve(1, 1, m); 88 return 0; 89 }
T3:
10pts的暴力是错的,超时了
三维偏序,设三个维度是a,b,c,分别按ab,bc,ac做三次二维偏序,若数对(i,j)满足三维偏序,那(i,j)在之前的二维偏序中一定被记录了三次,否则自会被记录一次或不被记录,所以三维偏序的数量就是前面三个二维偏序的总数M的$\frac{1}{2}\left ( M-\frac{n(n-1)}{2} \right )$,这样就解决q中没有-1的情况
有-1的话,三个维度分别为p,q,r,r是下标,做三次二维偏序,pr的就正常树状数组做,qr,pq的话就算出M的期望,扫描一下整个数组,算出每个数被-1的地方做了贡献的期望值,加起来再套上面的公式
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<map> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 9 inline int read() 10 { 11 int x = 0, f = 0; 12 char ch = getchar(); 13 while (!isdigit(ch)) f = ch == '-', ch = getchar(); 14 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 15 return f ? -x : x; 16 } 17 18 typedef long long LL; 19 20 const int N = 2000005; 21 int mod = 998244353, Inv = (mod + 1) / 2; 22 23 int n; 24 int tr[N], p[N], q[N], r[N], suf[N]; 25 26 LL modpow(LL a, int b) 27 { 28 LL res = 1; 29 for (; b; b >>= 1) 30 { 31 if (b & 1) res = res * a % mod; 32 a = a * a % mod; 33 } 34 return res; 35 } 36 37 void add(int x) 38 { 39 for (; x <= n; x += x & -x) ++tr[x]; 40 } 41 42 int ask(int x) 43 { 44 int res = 0; 45 for (; x; x -= x & -x) res += tr[x]; 46 return res; 47 } 48 49 LL solve(int* q) 50 { 51 LL ans = 0, sum = 0, inv = modpow(suf[1], mod - 2), cnt = 0; 52 memset(tr, 0, sizeof(tr)); 53 for (int i = 1; i <= n; i++) 54 { 55 if (q[i] > 0) 56 { 57 ans = (ans + ask(q[i]) + (suf[1] - suf[q[i]]) * cnt % mod * inv) % mod; 58 add(q[i]); 59 sum = (sum + suf[q[i]]) % mod; 60 } 61 else 62 { 63 ans = (ans + sum * inv + cnt * Inv) % mod; 64 ++cnt; 65 } 66 } 67 return ans; 68 } 69 70 int main() 71 { 72 scanf("%d", &n); 73 for (int i = 1; i <= n; i++) scanf("%d", p + i); 74 fill(suf + 1, suf + 1 + n, 1); 75 for (int i = 1; i <= n; i++) 76 { 77 scanf("%d", q + i); 78 r[p[i]] = q[i]; 79 if (q[i] > 0) suf[q[i]] = 0; 80 } 81 for (int i = n; i > 0; i--) suf[i] += suf[i + 1]; 82 83 LL ans = 0; 84 for (int i = 1; i <= n; i++) 85 { 86 ans += ask(p[i]); 87 add(p[i]); 88 } 89 ans += solve(q); 90 ans += solve(r); 91 ans -= (LL)n * (n - 1) / 2; 92 printf("%lld\n", (ans % mod + mod) * Inv % mod); 93 return 0; 94 }
T4:
不会
总结:
关于代码实现方面还要提升,总是想到思路不会实现,T2就想到了思路但不会实现,T3看了题解懂了也不会实现。不过现在倒是学会了nlogn的求三维偏序了,我还写了CDQ只有20分
浙公网安备 33010602011771号