• [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】


    题目链接:BZOJ - 2243

    题目分析

    树链剖分...写了200+行...Debug了整整一天+...

    静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了。

    提交之后全 WA 。

    ————————————— 杯具的分割线 —————————————————

    然后看了别人代码。。然后发现。。

    我写线段树区间修改竟然没打标记!!!!直接就修改上了!!!最裸的线段树都不会写了!!!

    Warning!Warning!Warning!

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    const int MaxN = 100000 + 5;
    
    int n, m, Index;
    int Father[MaxN], Son[MaxN], Depth[MaxN], Top[MaxN], A[MaxN], Size[MaxN], Pos[MaxN];
    int Color[MaxN];
    
    struct Edge
    {
    	int v;
    	Edge *Next;
    } E[MaxN * 2], *P = E, *Point[MaxN];
    
    inline void AddEdge(int x, int y) {
    	++P; P -> v = y;
    	P -> Next = Point[x]; Point[x] = P;
    }
    
    int DFS_1(int x, int Dep, int Fa) {
    	Depth[x] = Dep; 
    	Father[x] = Fa;
    	Size[x] = 1;
    	int SonSize, MaxSonSize;
    	SonSize = MaxSonSize = 0;
    	for (Edge *j = Point[x]; j; j = j -> Next) {
    		if (j -> v == Fa) continue;
    		SonSize = DFS_1(j -> v, Dep + 1, x);
    		if (SonSize > MaxSonSize) {
    			Son[x] = j -> v;
    			MaxSonSize = SonSize;
    		}
    		Size[x] += SonSize;
    	}
    	return Size[x];
    }
    
    void DFS_2(int x) {
    	if (x == 0) return;
    	if (x == Son[Father[x]]) Top[x] = Top[Father[x]];
    	else Top[x] = x;
    	Pos[x] = ++Index;
    	Color[Pos[x]] = A[x];
    	DFS_2(Son[x]);
    	for (Edge *j = Point[x]; j; j = j -> Next) {
    		if (j -> v == Father[x] || j -> v == Son[x]) continue;
    		DFS_2(j -> v);
    	}
    }
    
    struct ES 
    {
    	int Lx, Rx, Tx;
    	ES() {}
    	ES(int a, int b, int c) {
    		Lx = a; Rx = b; Tx = c;
    	}
    } T[MaxN * 4], D[MaxN * 4];
    
    ES Plus(ES e1, ES e2) {
    	ES ret;
    	if (e1.Tx == 0) return e2;
    	if (e2.Tx == 0) return e1;
    	ret = ES(e1.Lx, e2.Rx, e1.Tx + e2.Tx);
    	if (e1.Rx == e2.Lx) --ret.Tx;
    	return ret;
    }
    
    inline void Update(int x) {
    	T[x] = Plus(T[x << 1], T[x << 1 | 1]);
    }
    
    void Plant_Tree(int x, int s, int t) {
    	if (s == t) {
    		T[x] = ES(Color[s], Color[s], 1);
    		D[x] = ES(0, 0, 0);
    		return;
    	}
    	int m = (s + t) >> 1;
    	Plant_Tree(x << 1, s, m);
    	Plant_Tree(x << 1 | 1, m + 1, t);
    	Update(x);
    }
    
    inline void Paint(int x, ES Dlt) {
    	T[x] = Dlt;
    	D[x] = Dlt;
    }
    
    inline void PushDown(int x) {
    	if (D[x].Tx == 0) return;
    	Paint(x << 1, D[x]);
    	Paint(x << 1 | 1, D[x]);
    	D[x] = ES(0, 0, 0);
    }
    
    void Change_Tree(int x, int s, int t, int l, int r, int Col) {
    	if (l <= s && r >= t) {
    		ES Temp = ES(Col, Col, 1);
    		Paint(x, Temp);
    		return;	
    	}
    	PushDown(x);
    	int m = (s + t) >> 1;
    	if (l <= m) Change_Tree(x << 1, s, m, l, r, Col);
    	if (r >= m + 1) Change_Tree(x << 1 | 1, m + 1, t, l, r, Col);
    	Update(x);
    }
    
    void Change_Color(int x, int y, int z) {
    	int fx, fy;
    	while (true) {
    		fx = Top[x]; fy = Top[y];
    		if (Depth[fx] < Depth[fy]) {
    			swap(fx, fy);
    			swap(x, y);
    		}
    		if (fx == fy) {
    			if (Pos[x] < Pos[y]) Change_Tree(1, 1, n, Pos[x], Pos[y], z);
    			else Change_Tree(1, 1, n, Pos[y], Pos[x], z);
    			break;
    		}
    		else {
    			Change_Tree(1, 1, n, Pos[fx], Pos[x], z);
    			x = Father[fx];
    		}
    	}
    }
    
    ES Query_Tree(int x, int s, int t, int l, int r) {
    	if (l <= s && r >= t) return T[x];
    	PushDown(x);
    	int m = (s + t) >> 1;
    	ES ret = ES(0, 0, 0);
    	if (l <= m) ret = Plus(ret, Query_Tree(x << 1, s, m, l, r)); 
    	if (r >= m + 1) ret = Plus(ret, Query_Tree(x << 1 | 1, m + 1, t, l, r));
    	return ret;
    }
    
    int Query(int x, int y) {
    	int fx, fy, ret;
    	ES Ansx, Ansy, Temp;
    	Ansx = Ansy = ES(0, 0, 0);
    	while (true) {
    		fx = Top[x]; fy = Top[y];
    		if (Depth[fx] < Depth[fy]) {
    			swap(fx, fy);
    			swap(x, y);
    			swap(Ansx, Ansy);
    		}
    		if (fx == fy) {
    			ret = Ansx.Tx + Ansy.Tx;
    			if (Pos[x] < Pos[y]) {
    				Temp = Query_Tree(1, 1, n, Pos[x], Pos[y]);
    				ret += Temp.Tx;
    				if (Ansy.Lx == Temp.Rx) --ret;
    				if (Ansx.Lx == Temp.Lx) --ret;
    			}
    			else {
    				Temp = Query_Tree(1, 1, n, Pos[y], Pos[x]);
    				ret += Temp.Tx;
    				if (Ansx.Lx == Temp.Rx) --ret;
    				if (Ansy.Lx == Temp.Lx) --ret;
    			}
    			break;
    		}
    		else {
    			Ansx = Plus(Query_Tree(1, 1, n, Pos[fx], Pos[x]), Ansx);
    			x = Father[fx];
    		}
    	}
    	return ret;
    }
    
    int main() 
    {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
    	int a, b, c;
    	for (int i = 1; i <= n - 1; ++i) {
    		scanf("%d%d", &a, &b);
    		AddEdge(a, b);
    		AddEdge(b, a);
    	}
    	DFS_1(1, 0, 0);
    	Index = 0;
    	DFS_2(1);
    	Plant_Tree(1, 1, n);
    	char ch;
    	int Ans;
    	for (int i = 1; i <= m; ++i) {
    		ch = '#';
    		while (ch != 'C' && ch != 'Q') ch = getchar();
    		if (ch == 'C') {
    			scanf("%d%d%d", &a, &b, &c);
    			Change_Color(a, b, c);
    		}
    		else {
    			scanf("%d%d", &a, &b);
    			Ans = Query(a, b);
    			printf("%d
    ", Ans);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    leetcode(c++)计算器类
    java使用ffmpeg 实现图片、音频、视频添加水印功能(windows、linux)
    实验一密码引擎商用密码算法实现2交叉测试(选做)
    实验一密码引擎加密API研究
    微信小程序连接MQTT服务器、阿里云微消息队列MQTT版
    扫二维码进入小程序不同页面 微信小程序码生成详细方法步骤
    微信小程序之 wx.showToast延时跳转页面
    微信小程序订单页面
    精华文章
    .net core 华为云发送短信
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4225581.html
Copyright © 2020-2023  润新知