正睿20NOIp前冲刺day3

估分:10+7+0=17

实际:0+0+0=0

 

T1:

  没初始化,丢了暴力10分

  hash,每个点存储从1号点到他的路径上的点的hash值,用dfs序加树状数组来维护

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<time.h>
  4 #include<vector>
  5 #include<iostream>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 #define pb push_back
 10 #define lowbit(x) x&-x
 11 
 12 typedef unsigned long long ULL;
 13 
 14 const int N = 250010;
 15 const int P = 998244353;
 16 
 17 int n;
 18 int dep[N], dfn[N], ed[N], fa[N][25], tim;
 19 vector<int> e[N];
 20 ULL a[N], tr[N << 2];
 21 ULL vn[N], sum[N];
 22 
 23 void insert(int x, ULL c)
 24 {
 25     for (; x <= n; x += lowbit(x)) tr[x] ^= c;
 26 }
 27 
 28 ULL query(int x)
 29 {
 30     ULL res = 0;
 31     for (; x; x -= lowbit(x)) res ^= tr[x];
 32     return res;
 33 }
 34 
 35 void dfs(int u, int pa)
 36 {
 37     dfn[u] = ++tim;
 38     dep[u] = dep[pa] + 1;
 39     fa[u][0] = pa;
 40     for (int i = 1; i <= 20; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
 41     for (int i = 0; i < e[u].size(); i++)
 42     {
 43         int j = e[u][i];
 44         if (j == pa) continue;
 45         dfs(j, u);
 46     }
 47     ed[u] = tim;
 48 }
 49 
 50 int LCA(int x, int y)
 51 {
 52     if (dep[x] < dep[y]) swap(x, y);
 53     for (int i = 20; ~i; i--)
 54     {
 55         if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
 56     }
 57 
 58     if (x == y) return x;
 59     
 60     for (int i = 20; ~i; i--)
 61     {
 62         if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
 63     }
 64     return fa[x][0];
 65 }
 66 
 67 void init()
 68 {
 69     tim = 0;
 70     memset(dep, 0, sizeof(dep));
 71     memset(fa, 0, sizeof(fa));
 72     memset(tr, 0, sizeof(tr));
 73 }
 74 
 75 int main()
 76 {
 77     //freopen("input.txt", "r", stdin);
 78     vn[0] = 1;
 79     for (int i = 1; i <= 250000; i++) vn[i] = vn[i - 1] * P, sum[i] = sum[i - 1] ^ vn[i];
 80 
 81     int T;
 82     scanf("%d", &T);
 83     while (T--)
 84     {
 85         init();
 86         int q;
 87         scanf("%d%d", &n, &q);
 88         for (int i = 1; i <= n; i++) scanf("%llu", &a[i]), a[i] = vn[a[i]], e[i].clear();
 89         for (int i = 1; i < n; i++)
 90         {
 91             int x, y;
 92             scanf("%d%d", &x, &y);
 93             e[x].pb(y), e[y].pb(x);
 94         }
 95 
 96         dfs(1, 0);
 97         for (int i = 1; i <= n; i++) insert(dfn[i], a[i]), insert(ed[i] + 1, a[i]);
 98 
 99         while (q--)
100         {
101             int op, x, y;
102             scanf("%d%d%d", &op, &x, &y);
103             if (op == 1)
104             {
105                 int z = LCA(x, y);
106                 ULL num = query(dfn[x]) ^ query(dfn[y]) ^ a[z];
107                 if (num == sum[dep[x] + dep[y] - 2 * dep[z] + 1]) puts("Yes");
108                 else puts("No");
109             }
110             else
111             {
112                 ULL k = vn[y];
113                 insert(dfn[x], a[x] ^ k), insert(ed[x] + 1, a[x] ^ k);
114                 a[x] = k;
115             }
116         }
117     }
118 }
View Code

 

T2:

  数组开小+没开longlong,7分暴力没了

  将图中的点分为4类,G(啥也不坐),B(单车),S(在车站),T(地铁)。

  从 G->G,不需要连边。

  从 G->B:每一个对应的点连一条长度为 的边。

  从 B->G:每一个对应的点连一条长度为 的边。

  从 B->B:按照题目给出的自行车路线图,连边 。

  从G->S:每一个对应的点连一条长度为 的边。

  从 S->G:不连边。 从 S->S:不需要连边。

  从 S->T:每一个对应的点连一条长度为 的边。

  从 T->S:每一个对应的点连一个长度为 cici 的边。

  从 T->G:每一个对应的点连一条长度为 的边。

  从 T->T:按照地铁线路图连边。

  最后要加上等车时间,算进边权里就行,然后就直接跑dijkstra 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 typedef long long LL;
  9 
 10 const int N = 4e6 + 7;
 11 const LL INF = 1e18;
 12 const int MOD = 998244353;
 13 
 14 int n, m, r, s, k; 
 15 LL x;
 16 int G[N], B[N], S[N], T[N];
 17 int v[N];
 18 LL l[N];
 19 int idx = 0;
 20 int head[N], cnt;
 21 LL dis[N], e[N], c[N];
 22 bool vis[N];
 23 
 24 struct Node 
 25 {
 26     int id;
 27     LL dist;
 28     Node() {}
 29     Node(int id, LL dist) :id(id), dist(dist) {}
 30     bool operator < (const Node y) const 
 31     {
 32         return dist > y.dist;
 33     }
 34 };
 35 
 36 struct Edge 
 37 {
 38     int e, next;
 39     LL w, t, mod;
 40 }edge[N];
 41 
 42 void add(int s, int e, LL w, LL t, LL mod)
 43 {
 44     edge[++cnt].e = e;
 45     edge[cnt].w = w;
 46     edge[cnt].t = t;
 47     edge[cnt].mod = mod;
 48     edge[cnt].next = head[s];
 49     head[s] = cnt;
 50 }
 51 
 52 priority_queue<Node> q;
 53 
 54 void Dijstra(int s)
 55 {
 56     memset(vis, 0, sizeof(vis));
 57     for (int i = 1; i <= idx; ++i) dis[i] = INF;    
 58     dis[s] = 0;
 59     q.push(Node(s, 0));
 60     while (!q.empty())
 61     {
 62         Node x = q.top();    
 63         q.pop();
 64 
 65         int now = x.id;
 66         if (vis[now]) continue;
 67         vis[now] = 1;
 68         for (int i = head[now]; i; i = edge[i].next)
 69         {
 70             int to = edge[i].e;
 71             LL d = dis[now] + edge[i].w;
 72             LL wait = 0;
 73             if (edge[i].t) wait = (edge[i].mod - dis[now] % edge[i].t + edge[i].t) % edge[i].t;
 74             if (dis[to] > d + wait)
 75             {
 76                 dis[to] = d + wait;
 77                 q.push(Node(to, dis[to]));
 78             }
 79         }
 80     }
 81 }
 82 
 83 int main()
 84 {
 85     scanf("%d%d%d%lld", &n, &r, &s, &x);
 86     for (int i = 1; i <= n; ++i) scanf("%lld", &e[i]);
 87     for (int i = 1; i <= n; ++i) scanf("%lld", &c[i]);
 88     for (int i = 1; i <= n; ++i) G[i] = ++idx, B[i] = ++idx, S[i] = ++idx;
 89     for (int i = 1; i <= n; ++i) add(G[i], B[i], x, 0, 0), add(B[i], G[i], 0, 0, 0);
 90     for (int i = 1; i <= n; ++i) add(G[i], S[i], e[i], 0, 0);
 91     for (int i = 1; i <= r; ++i)
 92     {
 93         int u, v;
 94         LL w;
 95         scanf("%d%d%lld", &u, &v, &w);
 96         add(B[u], B[v], w, 0, 0);
 97         add(B[v], B[u], w, 0, 0);
 98     }
 99 
100     while (s--)
101     {
102         scanf("%d", &k);
103         for (int i = 1; i <= k; ++i) scanf("%d%lld", &v[i], &l[i]);
104         scanf("%d", &v[k + 1]);
105 
106         LL t;
107         scanf("%lld", &t);
108         for (int i = 1; i <= k; ++i) T[v[i]] = ++idx;
109         if (v[k + 1] != v[1]) T[v[k + 1]] = ++idx;
110 
111         LL mod = 0;
112         for (int i = 1; i <= k; ++i)
113         {
114             add(T[v[i]], T[v[i + 1]], l[i], t, mod);
115             mod = (mod + l[i]) % t;
116         }
117 
118         if (v[k + 1] == v[1]) mod = 0;
119         for (int i = k; i >= 1; --i)
120         {
121             add(T[v[i + 1]], T[v[i]], l[i], t, mod);
122             mod = (mod + l[i]) % t;
123         }
124         for (int i = 1; i <= k; ++i)
125         {
126             add(S[v[i]], T[v[i]], 0, 0, 0);
127             add(T[v[i]], S[v[i]], c[v[i]], 0, 0);
128             add(T[v[i]], G[v[i]], e[v[i]], 0, 0);
129         }
130 
131         if (v[k + 1] != v[1])
132         {
133             add(S[v[k + 1]], T[v[k + 1]], 0, 0, 0);
134             add(T[v[k + 1]], S[v[k + 1]], c[v[k + 1]], 0, 0);
135             add(T[v[k + 1]], G[v[k + 1]], e[v[k + 1]], 0, 0);
136         }
137     }
138     Dijstra(G[1]);
139     for (int i = 1; i <= n; ++i) printf("%lld ", dis[G[i]]);
140 }
View Code

 

T3:

  剪枝写错了,写成会炸int的了,10分暴力也没了

  玄学,不会写

 

总结:

  暴力容易写炸啊,之后还是要保证暴力绝对正确再写其他部分分。还有代码能力还是不行,第一题和第二题都想到正解的思路了,但不知道怎么写,第一题不知道hash函数怎么弄才好,第二题建图的代码没写完,第三题能得10分的剪枝想到了,但实现的方式不好,导致wa了。可能别人的代码看多了吧,代码能力不行,以后要多写题练练。

posted on 2020-10-14 17:14  ArrogHie  阅读(137)  评论(0编辑  收藏  举报