bzoj2631 tree

来源:互联网 发布:c语言error lnk2005 编辑:程序博客网 时间:2024/05/14 23:53

【想法】

 这几天的动态树做的头脑不清了。。尤其是因为原先的非主流模板,导致今天调了六七个小时才弄出来(不算写原来奇怪的模板的时间)。最后才发现原来是lct的rotate某一句前要在前面加上判断不是当前splay的根节点。

ch[f[y]][ch[f[y]][1] == y] = c;//在lct中这是错的,会修改轻边的父亲的儿子。。
if (!isroot(y)) ch[f[y]][ch[f[y]][1] == y] = c;//正确写法,加上判断

【参考资料】

 认真学习了Albafica大神的代码。

【代码】

代码1(主流代码,AC,18s不到,不知7s是怎么写出来的)
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <math.h>#define lch ch[c][0]#define rch ch[c][1]#define MEM(a) memset(a,0,sizeof(a))using namespace std;const int MAXN = 100010;const int INF = 999999999;const int MOD = 51061;int ch[MAXN][2], f[MAXN], rev[MAXN];unsigned int num[MAXN], sum[MAXN], s[MAXN], del1[MAXN], del2[MAXN];//del1 is +  del2 is *inline void up1(int c, int k){if (!c) return;del1[c] = del1[c] + k;if (del1[c] >= MOD) del1[c] = del1[c] % MOD;num[c] = num[c] + k;if (num[c] >= MOD) num[c] = num[c] % MOD;sum[c] = (k*s[c] + sum[c]) % MOD;}inline void up2(int c, int k){if (!c) return;del2[c] = k * del2[c] % MOD;del1[c] = k * del1[c] % MOD;num[c] = k * num[c] % MOD;sum[c] = k * sum[c] % MOD;}inline void down(int c){if (!c) return;if (rev[c]){swap(lch, rch);rev[lch] ^= 1;rev[rch] ^= 1;}if (del2[c] != 1){up2(lch, del2[c]);up2(rch, del2[c]);}if (del1[c]){up1(lch, del1[c]);up1(rch, del1[c]);}rev[c] = del1[c] = 0;del2[c] = 1;}void up(int c){if (!c) return;s[c] = s[lch] + s[rch] + 1;sum[c] = sum[lch] + sum[rch] + num[c];if (sum[c] >= MOD) sum[c] %= MOD;}inline bool isroot(int c) {return (!f[c] || ch[f[c]][0] != c&&ch[f[c]][1] != c);}void rotate(int c, int k){int y = f[c];ch[y][!k] = ch[c][k];if (ch[c][k]) f[ch[c][k]] = y;f[c] = f[y];if (!isroot(y)) ch[f[y]][ch[f[y]][1] == y] = c;f[y] = c;ch[c][k] = y;up(y);}void splay(int c){int y;down(c);while (!isroot(c)){if (isroot(f[c])) down(f[c]), down(c), rotate(c, ch[f[c]][0] == c);else{y = f[c];down(f[y]), down(y), down(c);if (ch[f[y]][0] == y) (ch[y][0] == c) ? (rotate(y, 1), rotate(c, 1)) : (rotate(c, 0), rotate(c, 1));else  (ch[y][1] == c) ? (rotate(y, 0), rotate(c, 0)) : (rotate(c, 1), rotate(c, 0));}}up(c);}int access(int c){int son = 0;for (; c; c = f[c]){splay(c);rch = son;up(son = c);}return son;}void root(int c){rev[access(c)] ^= 1;splay(c);}void link(int x, int u){root(x);f[x] = u;access(x);}void cut(int x, int u){root(x);access(u);splay(u);f[ch[u][0]] = 0;ch[u][0] = 0;up(u);}void work(){int i, t1, t2, t3, t4, t, n, q;char c;scanf("%d%d", &n, &q);for (i = 1; i <= n; ++i) num[i] = s[i] = del2[i] = sum[i] = 1;for (i = 1; i < n; ++i){scanf("%d%d", &t1, &t2);link(t1, t2);}for (i = 1; i <= q; ++i){c = getchar();while (c != '+'&&c != '-'&&c != '*'&&c != '/') c = getchar();scanf("%d%d", &t1, &t2);if (c == '+'){scanf("%d", &t3);root(t1);up1(access(t2), t3);splay(t2);}else if (c == '-'){scanf("%d%d", &t3, &t4);cut(t1, t2);link(t3, t4);}else if (c == '*'){scanf("%d", &t3);root(t1);up2(access(t2), t3);splay(t2);}else if (c == '/'){root(t1);printf("%d\n", sum[access(t2)]);splay(t2);}}}int main(){work();return 0;}
代码2(貌似是非主流的写法,狂TLE,但数据测试过是对的,求原因,到底是写渣了还是算法本身的问题)
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <math.h>#define lch ch[c][0]#define rch ch[c][1]#define MEM(a) memset(a,0,sizeof(a))using namespace std;const int MAXN = 100010;const int INF = 999999999;const int MOD = 51061;int ch[MAXN][2], f[MAXN], pa[MAXN], rev[MAXN];//pa是path_parent,貌似网上找都找不到这种写法。。。找到了请跟我说一声unsigned int num[MAXN], sum[MAXN], s[MAXN], del1[MAXN], del2[MAXN];//del1 is +  del2 is *inline void up1(int c, int k){if (!c) return;del1[c] = del1[c] + k;if (del1[c] >= MOD) del1[c] = del1[c] % MOD;num[c] = num[c] + k;if (num[c] >= MOD) num[c] = num[c] % MOD;sum[c] = (k*s[c] + sum[c]) % MOD;}inline void up2(int c, int k){if (!c) return;del2[c] = k * del2[c] % MOD;del1[c] = k * del1[c] % MOD;num[c] = k * num[c] % MOD;sum[c] = k * sum[c] % MOD;}inline void down(int c){if (!c) return;if (rev[c]){swap(lch, rch);rev[lch] ^= 1;rev[rch] ^= 1;}if (del2[c] != 1){up2(lch, del2[c]);up2(rch, del2[c]);}if (del1[c]){up1(lch, del1[c]);up1(rch, del1[c]);}rev[c] = del1[c] = 0;del2[c] = 1;}void up(int c){if (!c) return;//down(c);/////////////////////////////////////////////////s[c] = s[lch] + s[rch] + 1;sum[c] = sum[lch] + sum[rch] + num[c];if (sum[c] >= MOD) sum[c] %= MOD;}void check(){//printf("  i lc rc  f pa v sum  s d1 d2\n");//for (int i = 1; i <= 3; ++i) printf("%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d\n", i, ch[i][0], ch[i][1], f[i], pa[i], num[i], sum[i], s[i], del1[i], del2[i]);for (int i = 1; i <= 2000; ++i){if (ch[i][0] && f[ch[i][0]] != i || ch[i][1] && f[ch[i][1]] != i) printf("GX Error%d\n", i);}}void rotate(int c, int k){int y = f[c];//down(y); down(c);//上到下和上到下是不是一样的  在splay里更新是不是更快ch[y][!k] = ch[c][k];if (ch[c][k]) f[ch[c][k]] = y;f[c] = f[y];if (f[y]) ch[f[y]][ch[f[y]][1] == y] = c;f[y] = c;ch[c][k] = y;up(y);}void splay(int c){int y;down(c);while (f[c]){if (!f[f[c]]) down(f[c]), down(c), rotate(c, ch[f[c]][0] == c);else{y = f[c];down(f[y]), down(y), down(c);if (ch[f[y]][0] == y) (ch[y][0] == c) ? (rotate(y, 1), rotate(c, 1)) : (rotate(c, 0), rotate(c, 1));else  (ch[y][1] == c) ? (rotate(y, 0), rotate(c, 0)) : (rotate(c, 1), rotate(c, 0));}}up(c);}int find(int c){splay(c);while (lch){c = lch;down(c);///////////////////////}return c;}int access(int c){int son = 0, t;while (c){splay(c);f[rch] = 0;pa[find(rch)] = c;rch = son;f[son] = c;up(c);son = c;t = find(c);c = pa[t];pa[t] = 0;}return son;}void root(int c){rev[access(c)] ^= 1;splay(c);}void link(int x, int u){root(x);pa[x] = u;access(x);up(x);}void cut(int x, int u){root(x);access(u);splay(u);//if (ch[u][0] != x) printf("Root Error\n");f[ch[u][0]] = 0;ch[u][0] = 0;up(u);}void work(){int i, t1, t2, t3, t4, t, n, q;char c;scanf("%d%d", &n, &q);for (i = 1; i <= n; ++i) num[i] = s[i] = del2[i] = sum[i] = 1;for (i = 1; i < n; ++i){scanf("%d%d", &t1, &t2);link(t1, t2);}//check();for (i = 1; i <= q; ++i){c = getchar();while (c != '+'&&c != '-'&&c != '*'&&c != '/') c = getchar();scanf("%d%d", &t1, &t2);if (c == '+'){scanf("%d", &t3);root(t1);access(t2);splay(t2);up1(t2, t3);}else if (c == '-'){scanf("%d%d", &t3, &t4);cut(t1, t2);link(t3, t4);}else if (c == '*'){scanf("%d", &t3);root(t1);access(t2);splay(t2);up2(t2, t3);}else if (c == '/'){root(t1);printf("%d\n", sum[access(t2)]);splay(t2);}//check();}}int main(){work();return 0;}



0 0
原创粉丝点击