题目

很久很以前,有一个古老的村庄——xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着独立的生活,完全没有意识到其他n个人的存在。

但有一天,村民xiba臻无意中也得到了魔法,并发现了这个恐怖的事实。为了反抗村长,他走遍了全世界,找到了其他n个村民,并组织他们发动革命。但让这n个素不相识的村民(xiba臻已跟他们认识)同心协力去抵抗村长是很困难的,所以xiba臻决定先让他们互相认识。

这里,xiba臻用了xiba村特有的xiba思维:先让这n个人排成一列,并依次从1-n标号。然后每次xiba臻会选出一个区间[l, r],在这个区间中的人会去认识其他在这个区间中的人,但已经认识过得不会再去认识。这样,进行m次操作后,xiba臻认为这n个人能认识到许多人。

但是,为了精确地知道当前有多少对人已经认识了,xiba臻想要知道每次操作后会新产生出多少对认识的人,但这已是xiba思维无法解决的事了,你能帮帮他吗?

分析

很容易想到50%方法:

f[i]表示第i个人认识i+1~f[i],显然f[i]=max(f[i],r),答案边做边统计。

然后发现f是单调不下降的,所以就可以用带标记线段树维护区间最大值(当r<=最大值时,不可以统计答案)、最小值(当r<=最小值时,就不用往下做了)、以及区间和(统计答案用的),O(N)。


#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
using namespace std;
long long n,m,ans;
struct ljj
{
long long l,r,v,mn,mx,lf;
};
ljj tree[3000000];
long long set(long long v,long long l,long long r)
{
tree[v].l=l;
tree[v].r=r;
if(l==r)
{
tree[v].v=tree[v].mx=tree[v].mn=l;
return 0;
}
long long mid=(l+r)/2;
set(v*2,l,mid);
set(v*2+1,mid+1,r);
tree[v].v=tree[v*2].v+tree[v*2+1].v;
tree[v].mx=max(tree[v*2].mx,tree[v*2+1].mx);
tree[v].mn=min(tree[v*2].mn,tree[v*2+1].mn);
}
long long find(long long v,long long l,long long r,long long x,long long y,long long ri)
{
long long mid=(l+r)/2;
if(ri<=tree[v].mn) return 0;
if(l==r)
{
if(ri<=tree[v].mx) return 0;
tree[v].mx=ri;
tree[v].mn=ri;
long long g=ri-tree[v].v;
tree[v].v=ri;
return g;
}
if(ri<tree[v].mx)
{
long long g=tree[v].lf;
if(g)
{
tree[v*2].lf=tree[v*2+1].lf=g;
tree[v].lf=0;
tree[v*2].v=(mid-l+1)*g;
tree[v*2+1].v=(r-(mid+1)+1)*g;
tree[v*2].mx=tree[v*2].mn=tree[v*2+1].mx=tree[v*2+1].mn=g;
}
if(y<=mid)
{
g=find(v*2,l,mid,x,y,ri);
}
else
if(x>mid)
{
g=find(v*2+1,mid+1,r,x,y,ri);
}
else
{
g=find(v*2,l,mid,x,mid,ri)+find(v*2+1,mid+1,r,mid+1,y,ri);
}
tree[v].v=tree[v*2].v+tree[v*2+1].v;
tree[v].mx=max(tree[v*2].mx,tree[v*2+1].mx);
tree[v].mn=min(tree[v*2].mn,tree[v*2+1].mn);
return g;
}
else
{
if(l==x && y==r)
{
tree[v].lf=ri;
tree[v].mx=ri;
tree[v].mn=ri;
long long g=tree[v].v;
tree[v].v=ri*(r-l+1);
return tree[v].v-g;
}
else
{
long long g=tree[v].lf;
if(g)
{
tree[v*2].lf=tree[v*2+1].lf=g;
tree[v].lf=0;
tree[v*2].v=(mid-l+1)*g;
tree[v*2+1].v=(r-(mid+1)+1)*g;
tree[v*2].mx=tree[v*2].mn=tree[v*2+1].mx=tree[v*2+1].mn=g;
}
if(y<=mid)
{
g=find(v*2,l,mid,x,y,ri);
}
else
if(x>mid)
{
g=find(v*2+1,mid+1,r,x,y,ri);
}
else
{
g=find(v*2,l,mid,x,mid,ri)+find(v*2+1,mid+1,r,mid+1,y,ri);
}
tree[v].v=tree[v*2].v+tree[v*2+1].v;
tree[v].mx=max(tree[v*2].mx,tree[v*2+1].mx);
tree[v].mn=min(tree[v*2].mn,tree[v*2+1].mn);
return g;
}
}
}
int main()
{
long long i,j,k,x,y;
scanf("%lld%lld\n",&n,&m);
set(1,1,n);
for(i=1;i<=m;i++)
{
scanf("%lld%lld\n",&x,&y);
ans=find(1,1,n,x,y,y);
printf("%lld\n",ans);
}
}

【NOIP2015模拟11.2晚】我的天的更多相关文章

  1. JZOJ 4298. 【NOIP2015模拟11.2晚】我的天

    4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...

  2. 【NOIP2015模拟11.2晚】JZOJ8月4日提高组T2 我的天

    [NOIP2015模拟11.2晚]JZOJ8月4日提高组T2 我的天 题目 很久很以前,有一个古老的村庄--xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着 ...

  3. JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝

    Description

  4. [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告

    题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...

  5. 【NOIP2015模拟11.4】JZOJ8月6日提高组T1 刷题计划

    [NOIP2015模拟11.4]JZOJ8月6日提高组T1 刷题计划 题目 题解 题意 有\(n\)道题,编号为1~\(n\) 给出\(m\)次操作 每次操作有3种类型 1 \(x\) 表示交了\(A ...

  6. 【NOIP2015模拟11.5】JZOJ8月5日提高组T2 Lucas的数列

    [NOIP2015模拟11.5]JZOJ8月5日提高组T2 Lucas的数列 题目 PS:\(n*n*T*T<=10^{18}\)而不是\(10^1*8\) 题解 题意: 给出\(n\)个元素的 ...

  7. 【NOIP2015模拟11.5】JZOJ8月5日提高组T1 俄罗斯套娃

    [NOIP2015模拟11.5]JZOJ8月5日提高组T1 俄罗斯套娃 题目 题解 题意就是说 将1~\(n\)排列,问有多少种方案使得序列的逆序对个数小于\(k\) 很容易想到DP 设\(f[i][ ...

  8. 【NOIP2015模拟11.4】JZOJ2020年8月6日提高组T2 最优交换

    [NOIP2015模拟11.4]JZOJ2020年8月6日提高组T2 最优交换 题目 题解 题意 有一个长度为\(n\)的正整数 最多可以进行\(k\)次操作 每次操作交换相邻两个位置上的数 问可以得 ...

  9. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

随机推荐

  1. 阶段3 1.Mybatis_07.Mybatis的连接池及事务_2 连接池介绍

  2. Java基础之 多线程

    一.创建多线程程序的第一种方式: 继承(extends) Thread类 Thread类的子类: MyThread //1.创建一个Thread类的子类 public class MyThread e ...

  3. PHP开发一个简单的成绩录入系统

    预览界面 源码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  4. js if 判断的使用

    !DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> ...

  5. linux 正则表达式 目录

    linux 通配符与正则表达式 linux 通配符 linux 正则表达式 使用grep命令 linux 扩展正则表达式 egrep linux 正则表达式 元字符

  6. mybatis使用map传递多参数报错:A query was run and no Result Maps were found for the Mapped Statement

    在使用mybatis进行多参数传递时,报错: A query was run and no Result Maps were found for the Mapped Statement 'xx.xx ...

  7. 全新一台node节点加入到集群中

    目录 前言 对新节点做解析 方法一 hosts 文件解析 方法二 bind 解析 测试 分发密钥对 推送 CA 证书 flanneld 部署 推送flanneld二进制命令 推送flanneld秘钥 ...

  8. Codeforces 1262E Arson In Berland Forest(二维前缀和+二维差分+二分)

     题意是需要求最大的扩散时间,最后输出的是一开始的火源点,那么我们比较容易想到的是二分找最大值,但是我们在这满足这样的点的时候可以发现,在当前扩散时间k下,以这个点为中心的(2k+1)2的正方形块内必 ...

  9. JetBrains下载历史版本

    https://www.jetbrains.com/clion/download/other.html 在上方的链接中将clion改为idea,phpstrom.webstrom等等

  10. cmd常用快捷键

    Crtl + Shift +Enter : 以管理员的方式进入命令行模式 ESC: 清楚当前行的内容 Alt + Enter : 全屏/退出全屏 F7 : 通过列表形式查看历史记录 F4 : 快速删除 ...