제출 #892094

#제출 시각아이디문제언어결과실행 시간메모리
892094CutSandstoneRailway (BOI17_railway)C++17
36 / 100
68 ms23752 KiB
#include <bits/stdc++.h>
// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt,tune=native")
#define vi vector<int>
#define vb vector<bool>
#define vl vector<long long>
#define vii vector<vector<int>>
#define vll vector<vector<long long>>
#define pi pair<int, int>
#define pl pair<ll, ll>
#define vpi vector<pair<int, int>>
#define vpl vector<pair<ll, ll>>
#define a first
#define b second
#define str string
#define pb push_back
#define hset unordered_set
#define hmap unordered_map
const int mod = 1e9+7;
const int m = 998244353;
//16094558932
using namespace std;
using ll = long long;
using ull = unsigned ll;
template<size_t SZ> struct RMQ {
	static constexpr int level(int x) { return 31-__builtin_clz(x); }
	array<array<int,SZ>, level(SZ)+1> jmp;
	vi v;
	void init(const vi& depth, const vi& ind){
		v = depth;
		assert(ind.size() <= SZ);
		copy(begin(ind), end(ind), begin(jmp[0]));
		for (int j = 1; 1<<j <= ind.size(); ++j)
			for(int i = 0; i<ind.size()-(1<<j)+1; i++){
				int a = jmp[j-1][i], b = jmp[j-1][i+(1<<(j-1))];
				jmp[j][i] = depth[a] < depth[b] ? a:b;
			}
	}
	int query(int l, int r) {
		if(l > r) swap(l, r);
		int d = level(r-l+1);
		int a = jmp[d][l], b = jmp[d][r-(1<<d)+1];
		return v[a] < v[b] ? a:b;
	}
};
struct BIT {
	int N; vl data;
	void init(int sz){N = sz+1; data.resize(sz+1, 0); }
	void add(int p, ll x) { for (p++;p<=N;p+=p&-p) data[p-1] = (data[p-1]+x)%m; }
	ll sum(int l, int r) { return (sum(r)-(l==0?0:sum(l-1))+m)%m; }
	ll sum(int r) { ll s = 0; r++; for(;r;r-=r&-r)s = (s+data[r-1])%m; return s; }
	int lower_bound(ll sum) {
		if (sum <= 0) return -1;
		int pos = 0;
		for (int pw = 1<<25; pw; pw >>= 1) {
			int npos = pos+pw;
			if (npos <= N && data[npos-1] < sum)
				pos = npos, sum -= data[pos-1];
		}
		return pos;
	}
};
struct DSU {
	vector<int> e;
	DSU(int N) { e = vector<int>(N, -1); }
 
	// get representive component (uses path compression)
	int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); }
 
	bool same_set(int a, int b) { return get(a) == get(b); }
 
	int size(int x) { return -e[get(x)]; }
 
	bool unite(int x, int y) {  // union by size
		x = get(x), y = get(y);
		if (x == y) return false;
		if (e[x] > e[y]) swap(x, y);
		e[x] += e[y];
		e[y] = x;
		return true;
	}
};
struct Hasher {
	vl h1, h2, p1, p2, v1, v2;
	const ll m1 = 1283, m2 = 2793;
	const ll i1 = 439594703, i2 = 7876835;
	Hasher(string s){
		int n = s.size();
		h1.resize(n);
		h2.resize(n);
		p1.resize(n);
		p2.resize(n);
		v1.resize(n);
		v2.resize(n);
		for(int i = 0; i<n; i++){
			p1[i] = (i?p1[i-1]:i1)*m1%mod;
			p2[i] = (i?p2[i-1]:i2)*m2%mod;
			v1[i] = (i?v1[i-1]:m1)*i1%mod;
			v2[i] = (i?v2[i-1]:m2)*i2%mod;
			h1[i] = ((i?h1[i-1]:0)+p1[i]*(s[i]-'a'+1)%mod)%mod;
			h2[i] = ((i?h2[i-1]:0)+p2[i]*(s[i]-'a'+1)%mod)%mod;
		}
	}
	pi get(int l, int r){
		ll a = (h1[r]-(l?h1[l-1]:0)+mod)%mod;
		ll b = (h2[r]-(l?h2[l-1]:0)+mod)%mod;
		return {(int)(a*v1[l]%mod), (int)(b*v2[l]%mod)};
	}
};
struct SegTree {
	vll mem;
	int n;
	public:
	SegTree(int N){
		n = N;
		mem.resize(n<<1, vl(4));
	}
	void set(int ind, ll val){
		for(mem[ind+=n] = {val,val,val,val}; ind>>=1;) mem[ind] = comb(mem[ind<<1], mem[ind<<1|1]);
	}
	ll get(int l, int r){
		vl L = {}, R = {};
		for(l+=n,r+=n+1;l<r;l>>=1,r>>=1){
			if(l&1) L = comb(L, mem[l++]);
			if(r&1) R = comb(mem[--r], R);
		}
		return comb(L, R)[0];
	}
	private:
	vl comb(vl& l, vl& r){
		if(l.size() == 0) return r;
		if(r.size() == 0) return l;
		return {max({l[0], r[0], l[2]+r[1]}),
				max({l[3]+r[1], l[1]}),
				max({r[3]+l[2], r[2]}),
				l[3]+r[3]
			};
	}
};
class LZST {
private:
    class Node {
    public:
        ll l, r;
        Node *left, *right;
        ll val = 0, max = 0, min = 0, add = 0;
        bool isSet = false;
        Node(ll a, ll b) : l(a), r(b), left(nullptr), right(nullptr) {}
        void set(ll num) {
            isSet = true;
            add = max = min = num;
            val = num * (r - l + 1);
        }
        void addF(ll num) {
            add += num;
            val += num * (r - l + 1);
            max += num;
            min += num;
        }
        void prop() {
            ll mid = (l + r) >> 1;
            if (left == nullptr) left = new Node(l, mid);
            if (right == nullptr) right = new Node(mid + 1, r);
            if (isSet) {
                isSet = false;
                if (l != r) {
                    left->set(add);
                    right->set(add);
                }
            } else if (add != 0) {
                if (l != r) {
                    left->addF(add);
                    right->addF(add);
                }
            }
            add = 0;
        }
        void upd() {
            val = left->val + right->val;
            min = std::min(left->min, right->min);
            max = std::max(left->max, right->max);
        }
    };
    Node* top;
    void set(ll s, ll e, ll num, Node* curr) {
        if (curr->l == s && curr->r == e) {
            curr->set(num);
            return;
        }
        curr->prop();
        if (e <= curr->left->r) set(s, e, num, curr->left);
        else if (s >= curr->right->l) set(s, e, num, curr->right);
        else {
            set(s, curr->left->r, num, curr->left);
            set(curr->right->l, e, num, curr->right);
        }
        curr->upd();
    }
    void add(ll s, ll e, ll num, Node* curr) {
        if (curr->l == s && curr->r == e) {
            curr->addF(num);
            return;
        }
        curr->prop();
        if (e <= curr->left->r) add(s, e, num, curr->left);
        else if (s >= curr->right->l) add(s, e, num, curr->right);
        else {
            add(s, curr->left->r, num, curr->left);
            add(curr->right->l, e, num, curr->right);
        }
        curr->upd();
    }
    ll sum(ll s, ll e, Node* curr) {
        if (curr->l == s && curr->r == e) return curr->val;
        curr->prop();
        if (e <= curr->left->r) return sum(s, e, curr->left);
        if (s >= curr->right->l) return sum(s, e, curr->right);
        return sum(s, curr->left->r, curr->left) + sum(curr->right->l, e, curr->right);
    }
    ll max(ll s, ll e, Node* curr) {
        if (curr->l == s && curr->r == e) return curr->max;
        curr->prop();
        if (e <= curr->left->r) return max(s, e, curr->left);
        if (s >= curr->right->l) return max(s, e, curr->right);
        return std::max(max(s, curr->left->r, curr->left), max(curr->right->l, e, curr->right));
    }
    ll min(ll s, ll e, Node* curr) {
        if (curr->l == s && curr->r == e) return curr->min;
        curr->prop();
        if (e <= curr->left->r) return min(s, e, curr->left);
        if (s >= curr->right->l) return min(s, e, curr->right);
        return std::min(min(s, curr->left->r, curr->left), min(curr->right->l, e, curr->right));
    }
public:
    LZST(ll N) {
        assert(N > 0);
        top = new Node(0, N - 1);
    }
    ll get(ll s) {
        assert(s >= top->l && s <= top->r);
        Node* curr = top;
        stack<Node*> stk;
        while (curr->l != curr->r) {
            stk.push(curr);
            curr->prop();
            if (s <= curr->left->r) curr = curr->left;
            else curr = curr->right;
        }
        while (!stk.empty()) stk.top()->upd(), stk.pop();
        return curr->val;
    }
    ll sum(ll s, ll e) {
        assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e);
        return sum(s, e, top);
    }
    ll max(ll s, ll e) {
        assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e);
        return max(s, e, top);
    }
    ll min(ll s, ll e) {
        assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e);
        return min(s, e, top);
    }
    void add(ll s, ll e, ll num) {
        assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e);
        add(s, e, num, top);
    }
    void add(ll s, ll num) {
        assert(s >= top->l && s <= top->r);
        add(s, s, num, top);
	}
    void set(ll s, ll e, ll num) {
        assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e);
        set(s, e, num, top);
    }
    void set(ll s, ll num) {
        assert(s >= top->l && s <= top->r);
        set(s, s, num, top);
    }
};
const string name = "";
const int MAXN = 1e5, LOGN = 18;
vi g[MAXN];
int jp[MAXN][LOGN], timer = 0, tour[MAXN];
int depth[MAXN], st[MAXN], en[MAXN], cnt[MAXN];
int jump(int a, int k){
	for(int i = 0; i<LOGN; i++) 
		if((k>>i)&1) a = jp[a][i];
	return a;
}
int lca(int a, int b){
	if(depth[a] > depth[b]) swap(a, b);
	b = jump(b, depth[b]-depth[a]);
	if(a == b) return a;
	for(int i = LOGN-1; i>=0; i--) if(jp[a][i] != jp[b][i]){
		a = jp[a][i];
		b = jp[b][i];
	}
	return jp[a][0];
}
void dfs1(int s, int p){
	if(p+1) depth[s] = depth[p]+1;
	jp[s][0] = p;
	tour[st[s] = timer++] = s;
	for(int i: g[s]) if(i != p)
		dfs1(i, s);
	en[s] = timer-1;
}
void dfs2(int s, int p){
	for(int i: g[s]) if(i != p)
		dfs2(i, s);
	if(p != -1) cnt[p]+=cnt[s];
}
int main() {
	ios::sync_with_stdio(false);
  	cin.tie(nullptr);
	int n, m, k; cin >> n >> m >> k;
	vpi eg(n-1);
	for(int i = 0; i<n-1; i++){
		int a, b; cin >> a >> b;
		g[--a].pb(--b);
		g[b].pb(a);
		eg[i] = {a, b};
	}
	for(int i = 0; i<n; i++) for(int j = 0; j<LOGN; j++) jp[i][j] = -1;
	dfs1(0, -1);
	for(int i = 1; i<LOGN; i++) for(int j = 0; j<n; j++)
		if(jp[j][i-1] != -1) jp[j][i] = jp[jp[j][i-1]][i-1];
	while(m--){
		int total, top; cin >> total >> top;
		set<int> in;
		in.insert(st[--top]);
		while(--total){
			int s; cin >> s;
			int g = lca(--s, top);
			if(g == top){
				auto low = in.lower_bound(st[s]);
				auto high = low--;
				int end = -1;
				if(high != in.begin()) end = lca(s, tour[*low]);
				if(high != in.end()){
					int t = lca(s, tour[*high]);
					if(end == -1 || depth[t] > depth[end]) end = t;
				}
				cnt[s]++;
				cnt[end]--;
			}else{
				cnt[top]++;
				cnt[s]++;
				cnt[g]-=2;
				top = g;
			}
			in.insert(st[s]);
		}
	}
	dfs2(0, -1);
	vi edge(n);
	for(int i = 0; i<n-1; i++) if(depth[eg[i].a] > depth[eg[i].b])
		edge[eg[i].a] = i+1; else edge[eg[i].b] = i+1;
	vi ans;
	for(int i = 0; i<n; i++) if(cnt[i] >= k) ans.pb(edge[i]);
	cout << ans.size() << "\n";
	for(int i: ans) cout << i << " ";
	cout << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...