• [SHOI2013]发微博


    Description

    刚开通的SH微博共有n个用户(1..n标号),在短短一个月的时间内,用户们活动频繁,共有m条按时间顺序的记录:

    ​ ! x 表示用户x发了一条微博;

    ​ + x y 表示用户x和用户y成为了好友

    ​ - x y 表示用户x和用户y解除了好友关系

    当一个用户发微博的时候,所有他的好友(直接关系)都会看到他的消息。

    假设最开始所有人之间都不是好友关系,记录也都是合法的(即+ x y时x和y一定不是好友,而- x y时x和y一定是好友)。

    问这m条记录发生之后,每个用户分别看到了多少条消息。

    Input

    第1行2个整数n,m。

    接下来m行,按时间顺序读入m条记录,每条记录的格式如题目所述,用空格隔开。

    Output

    输出一行n个用空格隔开的数(行末无空格),第i个数表示用户i最后看到了几条消息。

    Sample Input

    2 8
    ! 1
    ! 2
    + 1 2
    ! 1
    ! 2
    - 1 2
    ! 1
    ! 2

    Sample Output

    1 1
    只有第4和第5条记录对应的消息被看到过。其他消息发送时,1和2不是好友。
    对100%的数据,N<=200000,M<=500000

    Solution

    还是按照惯例说我的思维过程。首先看到数据范围估计就是些什么数据结构(虽然最后避免了),然后觉得可不可能是并查集。。然后发现删去某条边不大好办,计算的时候复杂度也不低(可能是我太弱了)。

    然后想到有哪种数据结构能维护删边加边的——LCT。。。。省省吧。。这题的大众评的难度,注定了它与这东西无缘了。于是开始YY各种奇怪做法。

    考虑正难则反,我们先读入所有的数据之后,反着计算貌似比较容易。这么想,我们知道一个人x在后一段时间内发了一些微博,然后它与y在发这些微博之前成了好友,那么y自然也会收到这些。那么开一个cnt数组记录所发的微博数,然后如果他们成为了好友关系,就+cnt,如果断开了就互相-cnt。看上去没什么大毛病,交上去确实A掉。

    Code

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    #define re register
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define MAXN 1000001
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define ms(arr) memset(arr, 0, sizeof(arr))
    const int inf = 0x3f3f3f3f;
    int x[MAXN],y[MAXN],cnt[MAXN],ans[MAXN],n,m;
    char c[MAXN];
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-') c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    int main() 
    {
    	n=read();m=read();
    	for(re int i=1;i<=m;i++){
    		cin>>c[i];
    		if(c[i]=='!') x[i]=read();
    		else x[i]=read(),y[i]=read();
    	}
    	for(re int i=m;i>=1;i--){
    		if(c[i]=='!'){
    			cnt[x[i]]++;
    		}else if(c[i]=='+'){
    			ans[x[i]]+=cnt[y[i]];
    			ans[y[i]]+=cnt[x[i]];
    		}else {
    			ans[x[i]]-=cnt[y[i]];
    			ans[y[i]]-=cnt[x[i]];
    		}
    	}
    	for(re int i=1;i<=n;i++) printf("%d ", ans[i]);
        return 0;
    }
    
  • 相关阅读:
    [Objective-C语言教程]结构体(17)
    [Objective-C语言教程]字符串(16)
    [Swift]LeetCode827. 最大人工岛 | Making A Large Island
    [Swift]LeetCode826. 安排工作以达到最大收益 | Most Profit Assigning Work
    转 由一次磁盘告警引发的血案:du 和 ls 的区别
    Ant 参考
    转 Problem: AnyConnect was not able to establish a connection to the specified secu
    转 oracle 如何停下oracle 服务
    转: Windows如何打开和使用事件查看器管理计算机
    转: oracle 存储过程 执行动态 实现sql
  • 原文地址:https://www.cnblogs.com/victorique/p/9168721.html
Copyright © 2020-2023  润新知