正睿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 }
View Code

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 }
View Code

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 }
View Code

T4:

  不会

总结:

 关于代码实现方面还要提升,总是想到思路不会实现,T2就想到了思路但不会实现,T3看了题解懂了也不会实现。不过现在倒是学会了nlogn的求三维偏序了,我还写了CDQ只有20分

posted on 2020-10-30 16:39  ArrogHie  阅读(152)  评论(0)    收藏  举报