• [BZOJ 4419][Shoi2013]发微博


    4419: [Shoi2013]发微博

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 665  Solved: 364
    [Submit][Status][Discuss]

    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

    题解

    可以通过差分来进行维护操作. 我们可以考虑先开一个数组维护每一个用户当前发的信息数量, 然后再想办法快速维护某个用户的好友列表(可以偷懒用 $std::set$ 维护)

    差分的时候可以在加边的时候让对方的差分数据减去当前发过的信息数量, 删边的时候加上当前发过的信息数量. 最后统计答案的时候统一将所有好友发过的信息数量加上之前维护的差分数量就可以正确排斥非好友状态的信息了.

    参考代码

    GitHub

     1 #include <set>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <iostream>
     6 #include <algorithm>
     7 
     8 const int MAXN=2e5+10;
     9 
    10 int n;
    11 int m;
    12 int ans[MAXN];
    13 int cnt[MAXN];
    14 int delta[MAXN];
    15 std::set<int> lk[MAXN];
    16 
    17 char buf[10];
    18 
    19 int main(){
    20     int n,m;
    21     int a,b;
    22     scanf("%d%d",&n,&m);
    23     for(int i=0;i<m;i++){
    24         scanf("%s",buf);
    25         if(*buf=='!'){
    26             scanf("%d",&a);
    27             cnt[a]++;
    28         }
    29         else if(*buf=='+'){
    30             scanf("%d%d",&a,&b);
    31             delta[a]-=cnt[b];
    32             delta[b]-=cnt[a];
    33             lk[a].insert(b);
    34             lk[b].insert(a);
    35         }
    36         else if(*buf=='-'){
    37             scanf("%d%d",&a,&b);
    38             delta[a]+=cnt[b];
    39             delta[b]+=cnt[a];
    40             lk[a].erase(b);
    41             lk[b].erase(a);
    42         }
    43     }
    44     for(int i=1;i<=n;i++){
    45         for(std::set<int>::iterator it=lk[i].begin();it!=lk[i].end();++it){
    46             ans[*it]+=cnt[i];
    47         }
    48     }
    49     printf("%d",ans[1]+delta[1]);
    50     for(int i=2;i<=n;i++){
    51         printf(" %d",ans[i]+delta[i]);
    52     }
    53     putchar('
    ');
    54     return 0;
    55 }
    Backup

    日常图包

  • 相关阅读:
    gitlab10+版本删除项目工程
    Ubuntu16.04上通过anaconda3离线安装Tensorflow2.0详细教程
    android中根据smartRefeshLayout自定义上下拉刷新效果
    android高德地图根据经纬度添加标注(Marker)
    android设置状态栏颜色
    android复制内容到剪贴板
    android拨打电话的两种方式
    java集合转String数组
    解决jenkins部署TomcatManagerException问题
    SpringCloud 微服务消费者之间相互调用的方式
  • 原文地址:https://www.cnblogs.com/rvalue/p/7699063.html
Copyright © 2020-2023  润新知