首页 > 其他 > 详细

省选题泛做(长期坑

时间:2019-08-29 21:23:08      阅读:81      评论:0      收藏:0      [点我收藏+]

SDOI2019 快速查询

考虑维护双标记,题目的难点在于如何维护单点赋值操作。

推式子发现,直接修改原本的值变为$\frac{x-add}{mul}$,用hash维护下标即可。

技术分享图片
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define MOD 10000019
  4 namespace hash{
  5     #define sz 299999
  6     int h[300010], num[300010], clo[300010];
  7     int All, CLO;
  8     inline int get_Num(int x) {
  9         int wt = x % sz;
 10         while(num[wt] != x && num[wt]) {
 11             ++ wt;
 12             if(wt == sz) wt = 0;
 13         }
 14         num[wt] = x;
 15         return wt;
 16     }
 17     inline int upd(int x, int y, int CL) {
 18         int wt = get_Num(x);
 19         if(clo[wt] < CLO) h[wt] = All;
 20         int ret = y - h[wt];
 21         h[wt] = y; clo[wt] = CL;
 22         return ret;
 23     }
 24     inline int query(int x) {
 25         int wt = get_Num(x);
 26         if(clo[wt] < CLO) h[wt] = All, clo[wt] = CLO;
 27         return h[wt];
 28     }
 29 }
 30 int inv[MOD+10];
 31 inline void init() {
 32     inv[0] = inv[1] = 1;
 33     for(int i = 2; i < MOD; ++ i) {
 34         inv[i] = 1ll * inv[MOD % i] * (MOD - MOD / i) % MOD;
 35     }
 36 }
 37 struct Node {
 38     int op, x, y;
 39 } que[100010];
 40 int main() {
 41     //freopen("a.in", "r", stdin);
 42     init();
 43     int n, q;
 44     scanf("%d%d", &n, &q);
 45     for(int i = 1; i <= q; ++ i) {
 46           int op, x = 0, y = 0;
 47           scanf("%d", &op);
 48           if(op == 1) {
 49               scanf("%d%d", &x, &y);
 50               y %= MOD;
 51               y = (y + MOD) % MOD;
 52           }
 53           else if(2 <= op && op <= 5) {
 54               scanf("%d", &x);
 55               if(op != 5) {
 56                   x %= MOD;
 57                   x = (x + MOD) % MOD;
 58               }
 59           }
 60           //cerr << op << " " << x << " " << y << endl;
 61            que[i] = (Node){op, x, y};
 62        }
 63        int mul = 1, add = 0, sum = 0;
 64     int t;
 65     scanf("%d", &t);
 66     int Ans = 0, cnt = 0;
 67     while(t --) {
 68         int A, B;
 69         scanf("%d%d", &A, &B);
 70         //cerr << A << B << endl;
 71         for(int i = 1; i <= q; ++ i) {
 72             ++ cnt;
 73             int id = (A + 1ll * i * B) % q + 1;
 74             int op = que[id].op, x = que[id].x, y = que[id].y;
 75             if(op == 1) {
 76                 int ry = 1ll * (y - add + MOD) * inv[mul] % MOD;
 77                 int d = hash::upd(x, ry, cnt);
 78                 sum += d;
 79                 if(sum >= MOD) sum -= MOD;
 80                 if(sum < 0) sum += MOD;
 81             }
 82             else if(op == 2) {
 83                 add += x;
 84                 if(add >= MOD) add -= MOD;
 85             }
 86             else if(op == 4 || (op == 3 && x == 0)) {
 87                 sum = 1ll * n * x % MOD;
 88                 add = 0, mul = 1;
 89                 hash::All = (x + MOD) % MOD;
 90                 hash::CLO = cnt;
 91             }
 92             else if(op == 3) {
 93                 mul = 1ll * mul * x % MOD;
 94                 add = 1ll * add * x % MOD;
 95             }
 96             else if(op == 5) {
 97                 int res = hash::query(x);
 98                 res = (1ll * res * mul + add) % MOD;
 99                 Ans += res;
100                 if(Ans >= MOD) Ans -= MOD;
101             }
102             else {
103                 int res = (1ll * sum * mul + 1ll * n * add) % MOD;
104                 Ans += res;
105                 if(Ans >= MOD) Ans -= MOD;
106             }
107             if(mul < 0) mul += MOD;
108             if(add < 0) add += MOD;
109             if(sum < 0) sum += MOD;
110             //cerr << sum << endl;
111         }
112     }
113     printf("%d\n", Ans);
114 }
View Code

 

SDOI2019 热闹的聚会与尴尬的聚会

一道构造好题。

$\lfloor\frac{n}{p+1}\rfloor \leq q$可以推出$(p+1)(q+1)>n$。

每次枚举当前图中度数最小的点$x$,删除$x$以及与$x$相邻的点。

设总共会删除$q$次,显然有$\sum_{i=1}^q (d_i+1) = n$。

对于每次枚举的$x$度数中的最大值$mxd$,一定可以找到一个$p=mxd$的构造方案。

所以有$\sum_{i=1}^q (d_i+1)\leq mxd*q$。

稍加推倒可以证明如果找到$p=mxd$的构造方案,那么可以满足$(p+1)(q+1)>n$。

构造的方案即为当$d_x=mxd$时,当前图中剩余的全部点。

显然可以发现除了$x$以外,其他的点$y$满足$mxd \leq d_y$。

用$set$维护即可。

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct Edge{
 4     int u, v, Next;
 5 } G[200010];
 6 int head[100010], tot;
 7 int d[100010];
 8 struct Node{
 9     int D, x;
10     inline bool operator < (const Node& rhs) const{
11         return D < rhs.D || (D == rhs.D && x < rhs.x);
12     }
13 };
14 set<Node> S;
15 inline void add(int u, int v) {
16     G[++ tot] = (Edge){u, v, head[u]};
17     head[u] = tot;
18 }
19 int ans1[100010], t1;
20 int ans2[100010], t2;
21 inline void solve() {
22     int n, m;
23     scanf("%d%d", &n, &m);
24     tot = 0;
25     for(int i = 1; i <= n; ++ i) {
26         head[i] = -1;
27         d[i] = 0;
28     }
29     for(int i = 1; i <= m; ++ i) {
30         int u, v;
31         scanf("%d%d", &u, &v);
32         add(u, v), add(v, u);
33         ++ d[u], ++ d[v];
34     }
35     for(int i = 1; i <= n; ++ i) {
36         S.insert((Node){d[i], i});
37     }
38     int mxd = 0, pos;
39     t1 = t2 = 0;
40     while(!S.empty()) {
41         set<Node> :: iterator t = S.begin();
42         //cerr <<  "element " << t -> x << endl;
43         S.erase(t);
44         if(t -> D > mxd) {
45             mxd = t -> D;
46             pos = t1;
47         }
48         int x = t -> x;
49         ans2[++ t2] = x;
50         ans1[++ t1] = x;
51         for(int i = head[x]; i != -1; i = G[i].Next) {
52             t = S.find((Node){d[G[i].v], G[i].v});
53             
54             if(t == S.end()) continue;
55             //cerr << x << " " << G[i].v << endl;
56             int X = t -> x;
57             ans1[++ t1] = X;
58             S.erase(t);
59             for(int j = head[X]; j != -1; j = G[j].Next) {
60                 set<Node> :: iterator it = S.find((Node){d[G[j].v], G[j].v});
61                 if(it == S.end()) continue;
62                 S.erase(it);
63                 S.insert((Node){-- d[G[j].v], G[j].v});
64             }
65         }
66     }
67     printf("%d ", t1 - pos);
68     for(int i = pos + 1; i <= t1; ++ i) {
69         printf("%d ", ans1[i]);
70     }
71     puts("");
72     printf("%d ", t2);
73     for(int i = 1; i <= t2; ++ i) {
74         printf("%d ", ans2[i]);
75     }
76     puts("");
77 }
78 int main() {
79     int T;
80     scanf("%d", &T);
81     while(T --) {
82         solve();
83     }
84 }
View Code

 

省选题泛做(长期坑

原文:https://www.cnblogs.com/iamqzh233/p/11431853.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!