欲望以提升热忱,毅力以磨平高山!|

XichenOC

园龄:1个月粉丝:4关注:0

📂题解
🔖其他
2025-01-24 08:45阅读: 5评论: 0推荐: 0

P3998 [SHOI2013] 发微博

P3998 [SHOI2013] 发微博

题目翻译:

题目描述已经较为详细,这就不翻译了。

思路:

考虑暴力: 我们可以给每个人都添加一个关系链,每发出一次一条消息,就将所有与他有关系的答案依次加一。这样就统计出来了。但是这样的复杂度为 \(O(mn)\) 无法过。

考虑优化: 我们发现 \(m\) 次询问时难以优化掉的。考虑如何把 \(n\) 优化掉。我们发现暴力时每一次都要给所有人加一,那有什么办法可以不用每次都修改了?可以考虑前缀和。我们发现某一段有关系的区间内所加的消息数是等于,它那个人结束时发出的所有消息数,减去刚建立关系时的消息数,那我们只需要维护每个人发出消息数,在有人加入时,和退出时,分别减去和加上即可。

注意: 由于不一定所有人最后都会取消关系,所以我们最后要强制取消所有关系,那我们可以用 \(set\) 维护所有有关系的人,由于 \(set\) 操作都是 \(O(\log n)\) 的,所以最终复杂度为 \(O(m \log n)\)

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,cnt[N],ans[N];
set<int>s[N];
set<int>::iterator it;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=m;++i){
        char opt;
        cin>>opt;
        if(opt=='!'){
            int x;
            cin>>x;
            cnt[x]++;
        }
        if(opt=='+'){
            int x,y;
            cin>>x>>y;
            ans[x]-=cnt[y];
            ans[y]-=cnt[x];
            s[x].insert(y);
            s[y].insert(x);
            
        }
        if(opt=='-'){
            int x,y;
            cin>>x>>y;
            ans[x]+=cnt[y];
            ans[y]+=cnt[x];
            s[x].erase(y);
            s[y].erase(x);
        }
    }
    for(int i=1;i<=n;++i){
        for(it=s[i].begin();it!=s[i].end();++it){
            ans[i]+=cnt[*it];
        }
    }
    
    for(int i=1;i<=n;++i)cout<<ans[i]<<" ";
    return 0;
}

本文作者:XichenOC

本文链接:https://www.cnblogs.com/XichenOC/p/18689011

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   XichenOC  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起