博客
关于我
bzoj4419: [Shoi2013]发微博 (三种做法)
阅读量:314 次
发布时间:2019-03-03

本文共 2571 字,大约阅读时间需要 8 分钟。

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

感想

这题我有三个方法..

我的是最垃圾的。。
别的都很好

题解

1 线段树(我的)

这个做法很蠢啊。。写了4000B。。

最近思维退化,只会用线段树了

我们可以吧+和,-分开弄

然后离线可以知道每个人按时间顺序依次影响到的是哪些人。。
然后按顺序可以弄成一段连续的区间。。
对于每个人维护一个当前扫到右边的坐标,然后每一次他发信息就整体加上就好了
不想写了

#include
#include
#include
#include
using namespace std;const int N=200005;const int M=500005;int n,m;struct qq{ int c;//0:发微博 1:删除 2:加上 int x,y,id;}s[M],s1[M],s2[M];//原来的操作 增加操作 删除操作 bool cmp (qq a,qq b){ return a.x==b.x?a.id
>1; tr[a].s1=num+1;bt(l,mid); tr[a].s2=num+1;bt(mid+1,r);}void update (int now){ int s1=tr[now].s1,s2=tr[now].s2; tr[s1].c+=tr[now].c; tr[s2].c+=tr[now].c; tr[now].c=0;}void change (int now,int l,int r){ //printf("%d %d\n",l,r); if (l>r||l==0) return ; if (tr[now].l==l&&tr[now].r==r) { tr[now].c++; return ; } update(now); int s1=tr[now].s1,s2=tr[now].s2; int mid=(tr[now].l+tr[now].r)>>1; if (r<=mid) change(s1,l,r); else if (l>mid) change(s2,l,r); else change(s1,l,mid),change(s2,mid+1,r);}int ans[N];void dfs (int now,int f){ if (tr[now].l==tr[now].r) { ans[a[tr[now].l]]=ans[a[tr[now].l]]+tr[now].c*f; return ; } update(now); dfs(tr[now].s1,f);dfs(tr[now].s2,f);}void dfs1 (int now,int f){ if (tr[now].l==tr[now].r) { ans[b[tr[now].l]]=ans[b[tr[now].l]]+tr[now].c*f; return ; } update(now); dfs1(tr[now].s1,f);dfs1(tr[now].s2,f);}void solve (){//0:发微博 1:删除 2:加上 if (cnt>=1) { num=0;bt(1,cnt); for (int u=1;u<=m;u++) { if (s[u].c==2)//第一次我只弄减法 continue; //printf("%d %d %d %d %d\n",s[u].c,s[u].x,s[u].y,L[s[u].x],R[s[u].x]); if (s[u].c==0) change(1,L[s[u].x],R[s[u].x]); if (s[u].c==1)//减法 { R[s[u].x]++; R[s[u].y]++; } } dfs(1,-1); } /*for (int u=1;u<=n;u++) printf("%d ",ans[u]); printf("\n");*/ if (cnt1>=1) { num=0;bt(1,cnt1); for (int u=1;u<=m;u++) { if (s[u].c==1)//第一次我只弄加 continue; if (s[u].c==0)//加法 change(1,L1[s[u].x],R1[s[u].x]); if (s[u].c==2) { R1[s[u].x]++; R1[s[u].y]++; } } dfs1(1,1); } for (int u=1;u

2 O(n)的做法 CYS的

这个做法应该是最快的吗吧。。

我们就从后往前扫
对于每个人统计一个他当前发了多少个微博
然后当-的时候两个都减去互相当前的微博数
当+的时候两个都加上互相当前的微博数
就可以了

3 网上很普遍的做法 用set或者map都可以

然后set都烂大街了,不写了,网上一搜一大把

转载地址:http://ibcq.baihongyu.com/

你可能感兴趣的文章
nginx 反向代理 转发请求时,有时好有时没反应,产生原因及解决
查看>>
Nginx 反向代理解决跨域问题
查看>>
Nginx 反向代理配置去除前缀
查看>>
nginx 后端获取真实ip
查看>>
Nginx 多端口配置和访问异常问题的排查与优化
查看>>
Nginx 如何代理转发传递真实 ip 地址?
查看>>
Nginx 学习总结(16)—— 动静分离、压缩、缓存、黑白名单、性能等内容温习
查看>>
Nginx 学习总结(17)—— 8 个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
查看>>
Nginx 学习(一):Nginx 下载和启动
查看>>
nginx 常用指令配置总结
查看>>
Nginx 常用配置清单
查看>>
nginx 常用配置记录
查看>>
nginx 开启ssl模块 [emerg] the “ssl“ parameter requires ngx_http_ssl_module in /usr/local/nginx
查看>>
Nginx 我们必须知道的那些事
查看>>
Nginx 源码完全注释(11)ngx_spinlock
查看>>
Nginx 的 proxy_pass 使用简介
查看>>
Nginx 的配置文件中的 keepalive 介绍
查看>>
Nginx 结合 consul 实现动态负载均衡
查看>>
Nginx 负载均衡与权重配置解析
查看>>
Nginx 负载均衡详解
查看>>