zoukankan      html  css  js  c++  java
  • [CF1111E] Tree

    Portal

    题意很好懂, 就不讲了.

    主要问题在Dp方程式, 设(Dp[i][j])表示询问点中前(i)个点分成(j)个联通块的时候的方案数, 那么有:

    [Dp[i][j] = Dp[i - 1][j - 1] + Dp[i - 1][j] * (j - h[i]) ]

    (h[i])表示一个点到根的链上有多少个询问点.

    你发现询问点数很少. 并且是(sum k_i leq balabalal)的形式, 直接上虚树计算(h[i])

    时间复杂度(O(nlogn + (sum k) log (sum k) + sum m_i k _i))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define Debug(s) debug("The massage in line %d, Function %s: %s
    ", __LINE__, __FUNCTION__, s)
    typedef long long LL;
    typedef long double LD;
    int read() {
        char ch = getchar();
        int x = 0, flag = 1;
        for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
        for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        return x * flag;
    }
    void write(LL x) {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar(x % 10 + 48);
    }
    
    const int Maxn = 200009, Mod = 1e9 + 7;
    struct edge {
    	int to, nxt;
    }g[Maxn << 1];
    int n, head[Maxn], e, q;
    int fa[Maxn][21], dep[Maxn], Euler_clk, Beg[Maxn], End[Maxn];
    void add(int u, int v) { g[++e] = (edge){v, head[u]}, head[u] = e; }
    void dfsInit(int u, int pa) {
    	fa[u][0] = pa, dep[u] = dep[pa] + 1;
    	rep (i, 1, 20) fa[u][i] = fa[fa[u][i - 1]][i - 1];
    	Beg[u] = ++Euler_clk;
    	for (int i = head[u]; ~i; i = g[i].nxt) {
    		int v = g[i].to;
    		if (v != pa) dfsInit(v, u);
    	}
    	End[u] = ++Euler_clk;
    }
    
    void init() {
    	clar(head, -1);
    	n = read(), q = read();
    	rep (i, 1, n - 1) {
    		int u = read(), v = read();
    		add(u, v), add(v, u);
    	}
    
    	dfsInit(1, 0);
    }
    
    int LCA(int u, int v) {
    	if (dep[u] < dep[v]) swap(u, v);
    	drep (i, 20, 0) 
    		if (dep[fa[u][i]] >= dep[v]) u = fa[u][i];
    	if (u == v) return u;
    	drep (i, 20, 0)
    		if (fa[u][i] != fa[v][i]) 
    			u = fa[u][i], v = fa[v][i];
    	return fa[u][0];
    }
    
    int dp[309], instack[Maxn];
    vector <int> qset, Tmp;
    stack <int> s;
    vector <pair<int, int> > Fak;
    
    struct Tree {
    	edge g[Maxn << 1];
    	int head[Maxn], e, h[Maxn], mark[Maxn], vised[Maxn];
    	vector <int> ln;
    	void init() {
    		if (ln.size() == 0) clar(head, -1);
    		rep (i, 0, ln.size() - 1) 
    			head[ln[i]] = -1, h[ln[i]] = mark[ln[i]] = vised[ln[i]] = 0;
    		ln.clear(), e = 0;
    	}
    	void add(int u, int v) {
    		g[++e] = (edge){v, head[u]}, head[u] = e;
    		if (!vised[u]) ln.push_back(u), vised[u] = 1;
    	}
    	void setMark(int u) { mark[u] = 1; }
    	int getMark(int u) { return h[u] - mark[u]; }
    	void travel(int u, int pa) {
    		h[u] = h[pa] + mark[u];
    		for (int i = head[u]; ~i; i = g[i].nxt) {
    			int v = g[i].to;
    			if (v != pa) travel(v, u); 
    		}
    	}
    }lst;
    int cmp(int u, int v) {
    	return (u < 0 ? End[-u] : Beg[u]) < (v < 0 ? End[-v] : Beg[v]);
    }
    
    void solve() {
    	rep (Fake, 1, q) {
    		qset.clear(), Tmp.clear();
    		int k = read(), m = read(), r = read();
    		rep (i, 1, k) {
    			int u = read();
    			qset.push_back(u), instack[u] = 1;
    			Tmp.push_back(u);
    		}
    		if (!instack[r]) qset.push_back(r), instack[r] = 1;
    		sort(qset.begin(), qset.end(), cmp);	
    		rep (i, 1, qset.size() - 1) {
    			int l = LCA(qset[i - 1], qset[i]);
    			if (!instack[l]) instack[l] = 1, qset.push_back(l);
    		}
    		if (!instack[1]) instack[1] = 1, qset.push_back(1);
    		
    		rep (i, 0, qset.size() - 1) qset.push_back(-qset[i]);
    		sort(qset.begin(), qset.end(), cmp);	
    		
    		lst.init();
    		rep (i, 1, k) lst.setMark(Tmp[i - 1]);
    		
    		while (!s.empty()) s.pop();
    		rep (i, 0, qset.size() - 1) 
    			if (qset[i] > 0) s.push(qset[i]);
    			else {
    				int u = s.top(); s.pop(); instack[u] = 0;
    				if (u != 1) lst.add(s.top(), u), lst.add(u, s.top());
    			}
    		qset.clear(); 
    		lst.travel(r, 0);
    
    		int flag = 0;
    		rep (i, 1, k) flag |= (lst.getMark(Tmp[i - 1]) >= m);
    		if (flag) {
    			puts("0");
    			continue;
    		}
    
    		rep (j, 0, m) dp[j] = 0;
    		rep (i, 1, k) {
    			Fak.push_back(make_pair(lst.getMark(Tmp[i - 1]), Tmp[i - 1]));
    //			printf("%d %d
    ", lst.getMark(Tmp[i - 1]), Tmp[i - 1]);
    		}
    		sort(Fak.begin(), Fak.end());
    
    		dp[0] = 1;
    		rep (j, 1, k) 
    			drep (l, min(j, m), 0) 
    				if (l <= Fak[j - 1].first) dp[l] = 0;
    				else {	
    					dp[l] = 1ll * dp[l] * (l - Fak[j - 1].first) % Mod;
    					if (l > 0) dp[l] = (1ll * dp[l] + dp[l - 1]) % Mod;
    				}
    
    		Tmp.clear(), Fak.clear();
    		LL ans = 0;
    		rep (i, 1, m) (ans += dp[i]) %= Mod;
    		printf("%d
    ", ans);
    	}
    }
    
    int main() {
        freopen("CF1111E.in", "r", stdin);
        freopen("CF1111E.out", "w", stdout);
    
        init();
        solve();
    
    #ifdef Qrsikno
        debug("
    Running time: %.3lf(s)
    ", clock() * 1.0 / CLOCKS_PER_SEC);
    #endif
        return 0;
    }
    

    真的蛋疼, 调了一下午的BUG

    主要是判断答案不存在返回的时候要把东西一并清空(Line 98),或者直接在开头一并清除.

  • 相关阅读:
    小程序 wx.navigateTo和 wx.redirectTo区别
    小程序返回上一级页面背景音乐报错 setBackgroundAudioState:fail title is nil!;
    centos7 安装RabbitMQ3.6.15 以及各种报错
    MYSQL创建分区时候报错
    scrapy操作mysql/批量下载图片
    深入浅出TCP与IP协议笔记
    python反射详解
    python迭代器
    python生成器
    loggong模块
  • 原文地址:https://www.cnblogs.com/qrsikno/p/10354182.html
Copyright © 2011-2022 走看看