题意

有n只猴子排成一排,一共有m个笑话。开始时,这些猴子都坐在椅子上。下面m行给出的每个笑话包含三个整数x,l,k。代表猴子x讲了笑话l,所以距离x小于等于k的猴子如果他们从没听过这个笑话,他们会掉下椅子,如果听过这个笑话他们会爬回椅子上。问在讲完m个笑话以后,还有哪些猴子是还坐在椅子上的。

分析

当时在场上想到了是线段树,但是总是想保存下每个猴子听每个笑话听了几遍,发现数组都开不下,很难受。。

我们来看大佬们的想法:

对于每只猴子,它是在椅子上还是在地上只取决于它听到的最后一个笑话一共听了几遍。

所以我们首先要找出每只猴子听到的最后一个笑话是什么,然后再找出这个笑话他听了几遍。

我们可以想到用两颗线段树分别求这两个东西。第一颗线段树是比较好想的,关键是第二颗。

假设我们现在已经知道了每只猴子听到的最后一个笑话是什么。

对于每个笑话,我们在一颗线段树上做,做完以后删除。然后统计最后一个听到的笑话是这个的人的听的次数。这样遍历笑话和猴子,均摊是O(n)的,线段树的操作是logn(这段话来自大佬:https://www.cnblogs.com/huibixiaoxing/p/7678842.html,感谢指点)

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector> using namespace std;
const int maxn=+;
int T,n,m;
struct Node{
int l,r,num;
}node[maxn];
int x,l,k;
int set[*maxn],num[maxn];
void pushdown(int o){
if(set[o]){
set[*o]=set[o];
set[*o+]=set[o];
set[o]=;
}
}
int ql,qr,c;
void update(int o,int L,int R){
if(ql<=L&&qr>=R){
set[o]=c;
return;
}
pushdown(o);
int M=L+(R-L)/;
if(ql<=M)
update(*o,L,M);
if(qr>M)
update(*o+,M+,R);
return ;
}
int ask(int o,int L,int R,int p){
if(L==R){
return set[o];
}
pushdown(o);
int M=L+(R-L)/;
if(p<=M)
return ask(*o,L,M,p);
else
return ask(*o+,M+,R,p);
}
//*******以下是第二棵线段树
int sum[*maxn],addv[*maxn];
void pushdown2(int o){
if(addv[o]){
addv[*o]+=addv[o];addv[*o+]+=addv[o];
sum[*o]+=addv[o];sum[*o+]+=addv[o];
addv[o]=;
}
return ;
} void update2(int o,int L,int R){
if(ql<=L&&qr>=R){
addv[o]+=c;
sum[o]+=c;
return ;
}
pushdown2(o);
int M=L+(R-L)/;
if(ql<=M)
update2(*o,L,M);
if(qr>M)
update2(*o+,M+,R);
return;
}
int ask2(int o,int L,int R,int p){
if(L==R)return sum[o];
int M=L+(R-L)/;
pushdown2(o);
if(p<=M)
return ask2(*o,L,M,p);
else
return ask2(*o+,M+,R,p);
}
struct Interval{
int l,r;
};
vector<Interval>V1[maxn];
vector<int>V2[maxn];
int M,ans;
int main(){
scanf("%d",&T);
for(int t=;t<=T;t++){
M=-,ans=;
scanf("%d%d",&n,&m);
for(int i=;i<maxn;i++)V1[i].clear();
for(int i=;i<maxn;i++)V2[i].clear(); memset(set,,sizeof(set));
for(int i=;i<=m;i++){
scanf("%d%d%d",&x,&l,&k);
node[i].l=max(,x-k);
node[i].r=min(n,x+k);
node[i].num=l;
M=max(M,node[i].num);
V1[node[i].num].push_back((Interval){node[i].l,node[i].r});
ql=node[i].l,qr=node[i].r,c=node[i].num;
update(,,n);
}
for(int i=;i<=n;i++){
int g=ask(,,n,i);
// cout<<i<<" "<<g<<endl;
V2[g].push_back(i);
} memset(sum,,sizeof(sum));
memset(addv,,sizeof(addv));
/* for(int i=1;i<=M;i++){
printf("%d :",i);
for(int j=0;j<V2[i].size();j++){
printf("%d ",V2[i][j]);
}
printf("\n");
}*/
for(int i=;i<=M;i++){
// cout<<i<<endl;
for(int j=;j<V1[i].size();j++){
Interval inter=V1[i][j];
ql=inter.l,qr=inter.r,c=;
update2(,,n);
}
for(int j=;j<V2[i].size();j++){
if(ask2(,,n,V2[i][j])>=){
// printf("%d %d\n",V2[i][j],ask2(1,1,n,V2[i][j]));
ans++;
}
}
for(int j=;j<V1[i].size();j++){
Interval inter=V1[i][j];
ql=inter.l,qr=inter.r,c=-;
update2(,,n);
}
}
printf("%d\n",ans);
};
return ;

Gym101350 FMonkeying Around的更多相关文章

  1. gym101350 c h m

    C. Cheap Kangaroo time limit per test 1.0 s memory limit per test 256 MB input standard input output ...

  2. Gym101350 J Lazy Physics Cat

    参考博客:https://blog.csdn.net/lengqiu2015/article/details/76855681#reply 题意 给出一个长度为n的01串 我们定义F(x,y)是区间[ ...

随机推荐

  1. 配置文件Struts.xml 中type属性 redirect,redirectAction,chain的区别

    1.redirect:action处理完后重定向到一个视图资源(如:jsp页面),请求参数全部丢失,action处理结果也全部丢失.  2.redirectAction:action处理完后重定向到一 ...

  2. 剑指offer-第七章面试案例2(树中两个节点的公共祖先节点)

    import java.util.LinkedList; import java.util.Queue; import java.util.Stack; //树中两个节点的最低公共祖先 //第一种情况 ...

  3. HTTP 和 SOAP

    http:是一个客户端和服务器端请求和应答的标准(TCP).http协议其目的是为了提供一种发布和接收htttp页面的方法 一http协议的客户端与服务器的交互:由HTTP客户端发起一个请求,建立一个 ...

  4. 监听Documents文件夹内文件发生改变

    // 当Documents内文件发生改变时,启动计时器,每秒计算一次大小,当大小不发生改变时说明传输完毕,就开始刷新. @property (nonatomic, strong) NSTimer *t ...

  5. LOJ2823 「BalticOI 2014 Day 1」三个朋友

    题意 给定一个字符串 S,先将字符串 S 复制一次(变成双倍快乐),得到字符串 T,然后在 T 中插入一个字符,得到字符串 U. 给出字符串 U,重新构造出字符串 S. 所有字符串只包含大写英文字母. ...

  6. Linux 绑定双网卡

    1.立即关闭iptables并禁用开机自启动[root@mysql01 ~]# /etc/init.d/iptables stop[root@mysql01 ~]# chkconfig iptable ...

  7. C语言中的printf函数的输入输出问题

    这个问题是个很基础,但是我一直不知道的问题,是同学问了之后才知道的,长知识了. 这里要注意的是,printf函数是从右向左计算,从左向右输出. 距离如下: #include <stdio.h&g ...

  8. mysql的账号管理

    mysql的账号管理 最先匹配 user 表(包含:用户列 权限列 安全列 资源控制列)连接判断:host  user password字段(user的授权是全局的): 然后匹配db表:如果只是给指定 ...

  9. juc线程池原理(三):ThreadFactory、拒绝策略、提交任务、关闭线程池

    概要 (一) ThreadFactory 线程池中的ThreadFactory是一个线程工厂,线程池创建线程都是通过线程工厂对象(threadFactory)来完成的. 类图如下: 上面所说的thre ...

  10. 011. Python中*args, **kwargs 和 pass 和self 解释

    *args, **kwargs →在python都表示可变参数, *args表示任意多个任意类型无名参数, 是一个元组; **kwargs表示关键字参数(key/value参数), 是一个字典,接收的 ...