小 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. Java中弹出对话框中的几种方式

    1.显示一个错误对话框,该对话框显示的 message 为 'alert': JOptionPane.showMessageDialog(null, "alert", " ...

  2. vue.js vue-cli 中解决 axios 跨域调用的问题

    修改 /config/index.js 文件如下: proxyTable: { '/api': { target: 'http://chifan.local', changeOrigin: true, ...

  3. Jmeter如何把CSV文件的路径设置成一个变量,且变量的值是一个相对路径

    首先,在Jmeter中,通过User Defined Variables设置一个变量用来存储CSV文件所在文件夹的相对路径 备注: 这个相对路径前面不要加.\ 加了的话在运行的时候会报错,提示找不到那 ...

  4. 2018.08.30 bzoj4318: OSU!(期望dp)

    传送门 简单期望dp. 感觉跟Easy差不多,就是把平方差量进阶成了立方差量,原本维护的是(x+1)2−x2" role="presentation" style=&qu ...

  5. java-Runtime 调用命令

    java是一个跨平台的语言,可以在多种平台上运行相应的程序,但是有些时候进行数据的提取时,可能就需要系统的相关命令,尤其是调用linux命令 这时候就需要使用java的Runtime命令,来执行lin ...

  6. centos下安装visual studio code出现can't find libXss.so.1,出现这在类似怎么查找相关包

    在安装visual studio code时候.出现libXss.so.1被依赖,这个so文件要查看是属于那个包,通过此命令repoquery --nvr --whatprovides libXss. ...

  7. LDA汇总

    1.Blei的LDA代码(C):http://www.cs.princeton.edu/~blei/lda-c/index.html2.D.Bei的主页:http://www.cs.princeton ...

  8. LVDS_IP仿真分析

    这个一个对tx_outclock移相180度后的仿真结果. tx_outclock的时钟沿与数据中心对齐. tx_coreclock时钟与inclock时钟频率相等,但有相差.

  9. PriorityQueue源码分析

          PriorityQueue其实是一个优先队列,和先进先出(FIFO)的队列的区别在于,优先队列每次出队的元素都是优先级最高的元素.那么怎么确定哪一个元素的优先级最高呢,jdk中使用堆这么一 ...

  10. Lucene原理一

    Lucene 是一个高效的,基于Java 的全文检索库. 所以在了解Lucene之前要费一番工夫了解一下全文检索. 那么什么叫做全文检索呢?这要从我们生活中的数据说起. 我们生活中的数据总体分为两种: ...