• CF833D Red-Black Cobweb


    题面

    题解

    点分治大火题。。。

    设白边数量为$a$,黑边为$b$,则$2min(a,b)geq max(a,b)$

    即$2ageq b;&&2bgeq a$

    考虑点分治时如何统计答案:

    $2(a_1 +a_2) geq b_1 + b_2$

    $ herefore 2a_1-b_1geq b_2-2a_2$

    另外一边同理

    于是我们可以愉快地用$sort+BIT$统计答案了

    但是路径有可能重复计算,可以套一个$CDQ$分治什么的来搞一下

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define RG register
    #define clear(x, y) memset(x, y, sizeof(x));
    
    namespace IO
    {
    	const int BUFSIZE = 1 << 20;
    	char ibuf[BUFSIZE], *is = ibuf, *it = ibuf;
    	inline char getchar() { if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); return *is++; }
    }
    
    inline int read()
    {
    	int data = 0, w = 1;
    	char ch = IO::getchar();
    	while(ch != '-' && (ch < '0' || ch > '9')) ch = IO::getchar();
    	if(ch == '-') w = -1, ch = IO::getchar();
    	while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::getchar();
    	return data*w;
    }
    
    const int maxn(1e5 + 10), Mod(1e9 + 7);
    inline int fastpow(int x, int y)
    {
    	int ans = 1;
    	while(y)
    	{
    		if(y & 1) ans = 1ll * ans * x % Mod;
    		x = 1ll * x * x % Mod, y >>= 1;
    	}
    	return ans;
    }
    
    struct edge { int next, to, val, col; } e[maxn << 1];
    int n, head[maxn], e_num, size[maxn], Size, min, root;
    struct qry { int r, b, v, o; } stk[maxn], q[maxn << 2];
    int top, cntq, cntup, csum[maxn << 2], cmul[maxn << 2], vis[maxn];
    inline bool cmpr(const qry &a, const qry &b)
    	{ return a.r == b.r ? a.b < b.b : a.r < b.r; }
    
    void clean(int x)
    {
    	while(x <= (n << 2 | 1)) csum[x] = 0, cmul[x] = 1, x += x & -x;
    }
    
    void add(int x, int v)
    {
    	while(x <= (n << 2 | 1))
    		++csum[x], cmul[x] = 1ll * cmul[x] * v % Mod, x += x & -x;
    }
    
    int query_sum(int x)
    {
    	int ans = 0;
    	while(x) ans += csum[x], x -= x & -x;
    	return ans;
    }
    
    int query_mul(int x)
    {
    	int ans = 1;
    	while(x) ans = 1ll * ans * cmul[x] % Mod, x -= x & -x;
    	return ans;
    }
    
    inline void add_edge(int from, int to, int val, int col)
    {
    	e[++e_num] = (edge) {head[from], to, val, col};
    	head[from] = e_num;
    }
    
    void getRoot(int x, int fa)
    {
    	size[x] = 1; int tot = 0;
    	for(RG int i = head[x]; i; i = e[i].next)
    	{
    		int to = e[i].to; if(vis[to] || to == fa) continue;
    		getRoot(to, x); tot = std::max(tot, size[to]);
    		size[x] += size[to];
    	}
    	tot = std::max(tot, Size - size[x]);
    	if(tot < min) min = tot, root = x;
    }
    
    void getVal(int x, int fa, int r, int b, int v)
    {
    	stk[++top] = (qry) {r, b, v, 0};
    	for(RG int i = head[x]; i; i = e[i].next)
    	{
    		int to = e[i].to; if(vis[to] || to == fa) continue;
    		getVal(to, x, r + (!e[i].col), b + e[i].col, 1ll * v * e[i].val % Mod);
    	}
    }
    
    int ans = 1;
    void CDQ(int l, int r)
    {
    	if(l >= r) return;
    	int mid = (l + r) >> 1;
    	CDQ(l, mid); CDQ(mid + 1, r);
    	int j = l;
    	for(RG int i = mid + 1; i <= r; i++)
    	{
    		if(!q[i].o) continue;
    		while(q[j].r <= q[i].r && j <= mid)
    		{
    			if(!q[j].o) add(q[j].b, q[j].v);
    			++j;
    		}
    		ans = 1ll * ans * query_mul(q[i].b) % Mod *
    			fastpow(q[i].v, query_sum(q[i].b)) % Mod;
    	}
    	for(RG int i = l; i < j; i++) if(!q[i].o) clean(q[i].b);
    	std::inplace_merge(q + l, q + mid + 1, q + r + 1, cmpr);
    }
    
    void calc(int x)
    {
    	int PLUS = n << 1 | 1;
    	cntq = cntup = 0;
    	for(RG int i = head[x]; i; i = e[i].next)
    	{
    		int to = e[i].to; if(vis[to]) continue;
    		top = 0; getVal(to, x, !e[i].col, e[i].col, e[i].val);
    		for(RG int j = 1; j <= top; j++)
    		{
    			int a = stk[j].r, b = stk[j].b, c = 2 * a - b, d = 2 * b - a;
    			q[++cntq] = (qry) {c + PLUS, d + PLUS, stk[j].v, 1};
    		}
    		for(RG int j = 1; j <= top; j++)
    		{
    			int a = stk[j].r, b = stk[j].b, c = 2 * a - b, d = 2 * b - a;
    			q[++cntq] = (qry) {-c + PLUS, -d + PLUS, stk[j].v, 0};
    			if(2 * std::min(a, b) >= std::max(a, b))
    				ans = 1ll * ans * stk[j].v % Mod;
    		}
    	}
    	CDQ(1, cntq);
    }
    
    void dfs(int x)
    {
    	vis[x] = 1; calc(x);
    	for(RG int i = head[x]; i; i = e[i].next)
    	{
    		int to = e[i].to; if(vis[to]) continue;
    		Size = min = size[to]; getRoot(to, x); dfs(root);
    	}
    }
    
    int main()
    {
    	Size = min = n = read();
    	for(int i = 1, a, b, c, d; i < n; i++)
    		a = read(), b = read(), c = read(), d = read(),
    		add_edge(a, b, c, d), add_edge(b, a, c, d);
    	for(RG int i = 1; i <= (n << 2 | 1); i++) csum[i] = 0, cmul[i] = 1;
    	getRoot(1, 0); dfs(root);
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    置换笔记
    7.23
    Conveyor Belts
    CF #134 A~D
    Blocks && Fixing the Great wall
    Kakuro
    Deadlock Detection
    关于KeyFile的破解,含注册机源代码
    BMP位图之代码实现
    BMP位图之8位位图(三)
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10167577.html
Copyright © 2020-2023  润新知