• [题解] [JSOI2014] 歌剧表演


    题面

    题解

    我们可以把这些人拆成一些集合, 保证对于一个集合你只知道这个整体, 而无法分辨出哪一部分是哪些人

    起初所有人都在一个集合中

    我们对于每一次操作, 肯定会有一些人属于同一个集合

    那你就可以从这个集合中分辨出这些人来, 把这些人抠出来重新丢进一个集合

    最后一个人一个集合的就可以被分辨出来

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <set>
    const int N = 100005; 
    using namespace std;
    
    int n, m, id[N], a[N], ans[N], cnt = 1;
    set<int> s[N]; 
    
    template < typename T >
    inline T read()
    {
        T x = 0, w = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * w; 
    }
    
    bool cmp(int a, int b) { return id[a] < id[b]; }
    
    int main()
    {
        n = read <int> (), m = read <int> ();
        for(int i = 1; i <= n; i++) s[id[i] = 1].insert(i); 
        int num, last; 
        for(int t = 1; t <= m; t++)
        {
    	num = read <int> ();
    	for(int i = 1; i <= num; i++) a[i] = read <int> ();
    	sort(a + 1, a + num + 1, cmp), a[num + 1] = 0;
    	last = 1;
    	for(int i = 2; i <= num + 1; i++)
    	    if(id[a[i]] != id[a[i - 1]])
    	    {
    		for(int j = last; j < i; j++) s[id[a[j]]].erase(a[j]);
    		++cnt; 
    		if(s[id[a[last]]].size() == 1 && !ans[*s[id[a[last]]].begin()])
    		    ans[*s[id[a[last]]].begin()] = t; 
    		if(last == i - 1 && !ans[a[last]])
    		    ans[a[last]] = t;
    		for(int j = last; j < i; j++) s[id[a[j]] = cnt].insert(a[j]);
    		last = i; 
    	    }
        }
        for(int i = 1; i <= n; i++) printf("%d%c", ans[i], i == n ? '
    ' : ' '); 
        return 0; 
    }
    
  • 相关阅读:
    编译预处理命令define
    共享数据的包含const
    友元类,友元函数
    静态成员static
    this 指针
    构造函数与析构函数
    c++类的基础
    void指针和const指针
    c++基础
    组播的实现
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12296674.html
Copyright © 2020-2023  润新知