zoukankan      html  css  js  c++  java
  • [洛谷P3292][SCOI2016]幸运数字

    题目大意:给一棵$n(nleqslant2 imes10^4)$个点的树,$m(mleqslant2 imes10^5)$个询问,每次问$x->y$路径上的树异或最大值

    题解:可以点分治,线性基合并即可

    卡点:一处查询的地方写成了$maxn$

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    namespace __IO {
    	namespace R {
    		int x, ch;
    		inline int read() {
    			ch = getchar();
    			while (isspace(ch)) ch = getchar();
    			for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
    			return x;
    		}
    		long long X;
    		inline long long readll() {
    			ch = getchar();
    			while (isspace(ch)) ch = getchar();
    			for (X = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) X = X * 10 + (ch & 15);
    			return X;
    		}
    	}
    }
    using __IO::R::read;
    using __IO::R::readll;
    
    #define maxn 20010
    #define maxm 200010
    const int inf = 0x3f3f3f3f;
    
    int head[maxn], cnt = 1;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void addedge(int a, int b) {
    	e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    	e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
    }
    
    int headq[maxm], cntq = 1;
    struct Query {
    	int to, nxt;
    	bool vis;
    } qu[maxm << 1];
    inline void addquery(int a, int b) {
    	qu[++cntq] = (Query) {b, headq[a], false}; headq[a] = cntq;
    	qu[++cntq] = (Query) {a, headq[b], false}; headq[b] = cntq;
    }
    
    struct Base {
    #define M 60
    	long long s[M + 1];
    
    	inline Base& init() {
    		for (int i = 0; i <= M; i++) s[i] = 0;
    		return *this;
    	}
    	inline Base& insert(long long x) {
    		for (int i = M; ~i; i--) if (x >> i & 1) {
    			if (s[i]) x ^= s[i];
    			else {s[i] = x; break;}
    		}
    		return *this;
    	}
    	inline friend Base operator + (Base a, const Base &b) {
    		for (int i = M; ~i; i--) if (b.s[i]) a.insert(b.s[i]);
    		return a;
    	}
    	long long query() {
    		long long ans = 0;
    		for (int i = M; ~i; i--) if (ans < (ans ^ s[i])) ans ^= s[i];
    		return ans;
    	}
    #undef M
    } f[maxn];
    
    bool vis[maxn];
    namespace Center_of_Gravity {
    	int sz[maxn], __nodenum;
    	int root, MIN;
    #define n __nodenum
    	void __getroot(int u, int fa = 0) {
    		sz[u] = 1;
    		int MAX = 0;
    		for (int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if (v != fa && !vis[v]) {
    				__getroot(v, u);
    				sz[u] += sz[v];
    				MAX = std::max(MAX, sz[v]);
    			}
    		}
    		MAX = std::max(MAX, n - sz[u]);
    		if (MAX < MIN) MIN = MAX, root = u;
    	}
    	int getroot(int u, int nodenum = 0) {
    		n = nodenum ? nodenum : sz[u];
    		MIN = inf;
    		__getroot(u);
    		return root;
    	}
    #undef n
    }
    using Center_of_Gravity::getroot;
    
    int n, Q;
    long long w[maxn], ans[maxm];
    int S[maxn], top, bel[maxn];
    
    void getlist(int u, int fa, int tg) {
    	bel[S[top++] = u] = tg;
    	(f[u] = f[fa]).insert(w[u]);
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa && !vis[v]) getlist(v, u, tg);
    	}
    }
    void solve(int u) {
    	vis[u] = true, (f[u].init()).insert(w[u]), top = 0;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (!vis[v]) getlist(v, u, v);
    	}
    	for (int i = headq[u]; i; i = qu[i].nxt) if (!qu[i].vis){
    		ans[i >> 1] = f[qu[i].to].query();
    		qu[i].vis = qu[i ^ 1].vis = true;
    	}
    	for (int j = 0; j < top; j++) {
    		int u = S[j];
    		for (int i = headq[u]; i; i = qu[i].nxt) if (!qu[i].vis) {
    			int v = qu[i].to;
    			if (bel[u] != bel[v]) {
    				ans[i >> 1] = (f[u] + f[v]).query();
    				qu[i].vis = qu[i ^ 1].vis = true;
    			}
    		}
    	}
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (!vis[v]) solve(getroot(v));
    	}
    }
    
    int main() {
    	n = read(), Q = read();
    	for (int i = 1; i <= n; i++) w[i] = readll();
    	for (int i = 1, a, b; i < n; i++) {
    		a = read(), b = read();
    		addedge(a, b);
    	}
    	for (int i = 0, a, b; i < Q; i++) {
    		a = read(), b = read();
    		addquery(a, b);
    	}
    
    	solve(getroot(1, n));
    	for (int i = 1; i <= Q; i++) printf("%lld
    ", ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    两个类重复属性值复制
    IIS请求筛选模块被配置为拒绝超过请求内容长度的请求
    System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本问题
    Oracle 查询表中字段里数据是否有重复
    JS 中如何将<br/> 替换成 /n
    JS 验证数组中是否包含重复元素
    [C#] 使用NPOI将Datatable保存到Excel
    [C#] 将 List 转 DataTable
    [C#] 图文解说调用WebServer实例
    bzoj 3489: A simple rmq problem
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10098793.html
Copyright © 2011-2022 走看看