zoukankan      html  css  js  c++  java
  • BZOJ4419:[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好像还搞不了emmm……
    然后又想着能不能离线搞,发现+x y  -x y 只有他们之间的一段才会有贡献
    每个点单独开一个set,计算和其相连的人
    当为叹号的时候cnt++
    那么我们就在加的时候把当前cnt减掉,然后在后面减的时候再加上新的cnt,
    这一段区间内的贡献就都被考虑进去了
    最后再遍历一遍set把过程中没有减掉的贡献算上就行了

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<set>
     4 #define N (200005)
     5 using namespace std;
     6 set<int>s[N];
     7 set<int>::iterator po;
     8 int n,m,x,y,cnt[N],ans[N];
     9 char opt[2];
    10 int main()
    11 {
    12     scanf("%d%d",&n,&m);
    13     for (int i=1; i<=m; ++i)
    14     {
    15         scanf("%s",opt);
    16         switch (opt[0])
    17         {
    18             case '!':
    19             {
    20                 scanf("%d",&x);
    21                 cnt[x]++;
    22                 break;
    23             }
    24             case '+':
    25             {
    26                 scanf("%d%d",&x,&y);
    27                 s[y].insert(x);
    28                 s[x].insert(y);
    29                 ans[x]-=cnt[y];
    30                 ans[y]-=cnt[x];
    31                 break;
    32             }
    33             case '-':
    34             {
    35                 scanf("%d%d",&x,&y);
    36                 s[y].erase(s[y].find(x));
    37                 s[x].erase(s[x].find(y));
    38                 ans[x]+=cnt[y];
    39                 ans[y]+=cnt[x];
    40                 break;
    41             }
    42         }
    43     }
    44     for (int i=1; i<=n; i++)
    45         for (po=s[i].begin(); po!=s[i].end(); ++po)
    46             ans[*po]+=cnt[i];
    47     for (int i=1; i<=n-1; ++i)
    48         printf("%d ",ans[i]);
    49     printf("%d",ans[n]);
    50 }
  • 相关阅读:
    转载: RAID详解[RAID0/RAID1/RAID10/RAID5]
    用户交互式命令:read
    linux下fdisk分区管理、文件系统管理、挂载文件系统等
    linux文件系统下的特殊权限
    find命令详解
    python3中 getpass模块使用
    个人shell积累
    手把手教你利用爬虫爬网页(Python代码)
    数通HCIP-ospf知识点
    HCIE之路--超全ospf思维导图
  • 原文地址:https://www.cnblogs.com/refun/p/8685664.html
Copyright © 2011-2022 走看看