小 S 热爱大自然, 一天他种了一棵奇怪的线段树.

奇怪的线段树是一种与普通线段树类似的结构, 唯一不同的是, 它不一定以每一个区间的中点作为分治中心.

麻烦的是, 小 S 的线段树被风吹散了, 散成了一个个表示单一区间的结点, 而且正在逐渐飘远. 不过小 S 早有准备, 他可以进行抓取操作, 每一次他可以给出一个抓取区间, 由于这个抓取区间只有两个端点有磁力, 所以只能抓取满足与抓取区间有交而不被抓取区间包含的所有线段树结点.

现在小 S 进行了若干次抓取操作, 对于每次操作, 他希望你能回答他一共抓取了多少个线段树结点.

這道題給出了m個區間,要求我們求構造出來的樹之中,與當前區間有交集關係而且當前區間不包含的區間到底有多少個

首先是建樹問題,我們可以按照題意遞歸建樹,看一下現在的l是否==r,不然return,否則輸入當前區間的mid,並且遞歸左子樹和右子樹,所有區間可以使用一個結構體來存下來

然後再將詢問和線段樹區間按照右端點排序

而且,這道題有區間關係,應該想到掃描線

但是,在這道題中,如果直接求出答案,會很複雜,需要很多分類討論,正難則反,所以我們可以求出與當前詢問區間不相交的區間個數

這種類型有3個:

1.該區間右端點在當前區間左端點的左邊

2.該區間被現在的區間包含

3.該區間左端點在當前區間右端點的右邊

將這些算出來以後,所有區間個數-1類個數-2類-3類個數就是當前詢問區間個數的答案

對於1:我們可以維護一個樹狀數組,其維護了當前位置合法區間右端點的前綴和。每次移動一個區間時,不斷的將下一個線段樹區間加入樹狀數組,直到下一個區間的左端點在該區間裡面。然後,查詢當前區間左端點左邊有多少個右端點,就知道了與當前區間不相交的線段個數,這樣得到了ans1

對於2:可以再維護一個樹狀數組,初始,其將所有線段樹區間的右端點都加了進去。每一次移動區間時,不斷的將下一個線段樹區間從數組刪除,知道下一個區間的左端點在該區間裡面,則我們已經去除了所有l不在這個區間的線段。現在當前的所有區間的l值都大於現在查詢區間的l值,但是我們還想要現在查詢的右端點大於當前所有區間的右端點,所以得查詢一下有多少個右端點在區間l-r中

對於3,也可以再使用一個樹狀數組維護,但是我們發現,只要維護一個後綴和,記錄有多少個區間的l值大於等於現在的l值即可,因為如果有區間的l值大於現在查詢區間的r值,則這個區間的r值一定大於查詢區間的r值。

所以我們減去即可,所有查詢區間要存id表示它是第幾個詢問

#include<bits/stdc++.h>
using namespace std;
int n,m,b[300010],c[300010],s[300010],ans[3000010];
struct no{
    int l,r,id;
    bool operator <(const no &rhs)const{
        return l<rhs.l;
    }
}x[3000010],y[3000010];
int ct=0;
void get(int l,int r){
    if(l==r)return;
    x[++ct]=(no){l,r,0};
    int mid;
    scanf("%d",&mid);
    get(l,mid);get(mid+1,r);
}
void mod1(int x,int y){for(int i=x;i<=n;i+=(i&-i))b[i]+=y;}
void mod2(int x,int y){for(int i=x;i<=n;i+=(i&-i))c[i]+=y;}
int q1(int x){
    int ans=0;
    while(x){
        ans+=b[x];
        x-=x&-x;
    }
    return ans;
}
int q2(int x){
    int ans=0;
    while(x){
        ans+=c[x];
        x-=x&-x;
    }
    return ans;
}
int main(){
    freopen("strange.in","r",stdin);
    freopen("strange.out","w",stdout);
    scanf("%d%d",&n,&m);
    get(1,n);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&y[i].l,&y[i].r);
        y[i].id=i;
    }
    sort(x+1,x+ct+1);
    sort(y+1,y+m+1);
    for(int i=1;i<=ct;i++){
        s[x[i].l]++;
        mod2(x[i].r,1);
    }
    for(int i=n;i>=1;i--)
        s[i]=s[i]+s[i+1];
    int now=1;
    for(int i=1;i<=m;i++){
        while(now<=ct&&x[now].l<y[i].l){
            mod2(x[now].r,-1);
            mod1(x[now].r,1);
            now++;
        }
        ans[y[i].id]=ct-q1(y[i].l-1)-q2(y[i].r)+q2(y[i].l-1)-s[y[i].r+1];
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
}

jzoj5848的更多相关文章

随机推荐

  1. TYVJ 1940 创世纪

    Description: 上帝手中有着 N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放到一个新的空间中去以建造世界.每 种世界元素都可以限制另外一种世界元素,所以说上帝希望所有被投放的世 ...

  2. 品味性能之道<六>:图形化SQL分析工具

         在上一章里,重点分享了命令行SQL分析工具的使用方法.在本章将重点分享PL/SQL的SQL分析工具. 一.如何打开PL/SQL执行计划      开启PL/SQL这工具,推荐如下方法: 点击 ...

  3. 彻底关闭win10的自动更新,一定要坚持看到最后一页

    https://jingyan.baidu.com/article/9faa7231e7b78b473c28cbb6.html 是否好使我还在测试,不好使的话,再跟新 2018-05-20 今天电脑又 ...

  4. part1:8-远程登录Linux

    Linux远程登录 Linux系统中是通过ssh服务实现的远程登录功能.默认ssh服务开启了22端口,而且在安装完成系统时,这个服务已经安装,并且是开机启动的.所以不需要额外配置就能直接远程登录Lin ...

  5. 如何查看路由器的mac和计算机的mac

    如何查看路由器的mac和计算机的mac 一.查看路由器的mac 方法一: 直接看路由器的背面,如下图,即可看到MAC地址   打开命令提示符窗口,输入ipconfig,找到网关地址,如192.168. ...

  6. java实现word,ppt,excel,jpg转pdf

    word,excel,jpeg 转 pdf 首先下载相关jar包:http://download.csdn.net/detail/xu281828044/6922499 import java.io. ...

  7. css样式记忆

    text-indent: 2em;   //开头空两格: display : none;    //隐藏元素 background:#CCC;  //背景颜色 background: url(imag ...

  8. 2018.08.30 Tyvj1952 Easy(期望dp)

    Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:( 我们来简化一下这个游戏的规则 有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连 ...

  9. 【转】MapReduce:详解Shuffle过程

    ——转自:{http://langyu.iteye.com/blog/992916} Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方.要想理解MapReduce, Shuffle ...

  10. Oracle实例名,服务名等概念区别与联系

    数据库名.实例名.数据库域名.全局数据库名.服务名 , 这是几个令很多初学者容易混淆的概念.相信很多初学者都与我一样被标题上这些个概念搞得一头雾水.我们现在就来把它们弄个明白. 一.数据库名 什么是数 ...