NOIP模擬 被粉碎的線段樹

2021-07-22 09:25:29 字數 1639 閱讀 5692

不會做啊!打了個貪心,沒有加倍增,然後在打了幾個特殊情況拿了85分。

其實答案有乙個性質:區間的定位個數=2*區間的長度-完全被包含的區間個數,比如說[2,7]的答案=(7-2+1)*2-9=3,包含的區間([2,2],[3,3],[4,4],[5,5],[2,3],[5,7],[6,7],[6,6],[7,7])。

好神奇啊!

為什麼nie?(感覺我是個弱智)

乙個線段樹中的區間[l,r],包括他自己和下面的區間一共有2*(r-l+1)-1個區間,所以我用2*(r-l+1)減去這些完全被包含的區間個數就會的出乙個1。對於詢問的[l,r],因為不一定是線段樹中的區間,所以含有很多棵樹,乙個樹可以用乙個1來表示(就相當於用乙個已經最大的區間來包含),這些樹的集合是所有被包含在這個區間的區間的個數(及所有[l』,r』]的區間滿足l』≥l,r』≤r)。

這個二元偏序關係的計數,可以用樹狀陣列來實現,把所有的詢問和區間按照左端點排序,然後限制l的關係,把所有的r放進樹狀陣列裡面,然後查詢一下就好了。

#include

#include

#include

#include

#include

#define fo(i,a,b) for(i=a;i<=b;i++)

#define fod(i,a,b) for(i=a;i>=b;i--)

#define rep(i,a) for(i=first[a];i;i=next[i])

using

namespace

std;

const

int maxn=100007;

int i,j,k,n,m,ans[maxn],l,r;

int a[maxn],dfn,tongl,tongr;

int num;

int t[maxn*30];

struct nodeduan[maxn*30],wen[maxn];

void build(int x,int l,int r)

int mid=a[++dfn];

build(x*2,l,mid);

build(x*2+1,mid+1,r);

duan[++num].l=l,duan[num].r=r;

}bool cmp(node x,node y)

void add(int x,int y)

int find(int x)

int main()

build(1,1,n);

fo(i,1,m)scanf("%d%d",&wen[i].l,&wen[i].r),wen[i].c=i;

sort(wen+1,wen+1+m,cmp);

sort(duan+1,duan+1+num,cmp);

k=1;

fo(i,1,num)add(duan[i].r,1);

fo(i,1,m)

fo(i,1,m)printf("%d\n",ans[i]);

}

NOIP模擬 排列 權值線段樹

題目大意 對於乙個1到n的排列,若知道每一位的逆序數 第i位a i 的逆序數就是a 1 a i 1 中比a i 大的數的個數 則能求出原排列。現在對於排列,給出。p i 表示a 1 a i 的逆序數和。請你求出原排列。1 n 100000 解題思路 先求出每個數的逆序數,仍設為p i 倒著確定,那對...

NOIP模擬 奇襲 線段樹 單調棧

題意 給定數列,求有多少個區間滿足區間最大 1 區間最小 區間長度 滿足條件為 m ax 1 m in r 1 l ma x mi n r lmax 1 min r 1 l max min r l max 1 min r 1 l ma x mi n r lma x mi n l rmax min l...

Jzoj4747 被粉碎的線段樹

額這個題麼 有乙個很關鍵的點 結點個數依然為2n 1 證明可以看sam的講稿 不難發現以下性質 區間定位個數 區間所覆蓋的節點個數 2 區間長度 所以問題變為,乙個區間覆蓋了多少個節點?我們可以求出所有的節點,然後這個問題就是乙個二維偏序計數問題了 具體用離線 按照r排序套上樹狀陣列即可 inclu...