bzoj 2141 排隊 樹套樹

2021-07-25 19:08:22 字數 1764 閱讀 3716

交換位置l,r,對答案產生的影響是l,r內(比l大的數個數-比l小的數個數)+(比r小的數個數-比r大的數的個數)+(l和r交換後應該+1或-1)。求這個東西用樹套樹就可以(做資料結構做傻了,還有很多其他優秀的做法)。

#include

#include

#include

#define maxn 1700005

using

namespace

std;

void read(int &a)

}int a[20005];

int lsh[20005];

struct xdstree[400005];

int n,m;

int val[maxn],sz[maxn];

int ch[maxn][2],fa[maxn];

int cnt[maxn],tot,d;

bool dir(int x)

void up(int x)

void rotate(int x)

void splay(int x,int e)

else

}}

}int nxt,t1;

int pre,t2;

void find_nxt(int p,int x)

}void insert(int f,int &x,int k)

if(val[x]==k)

sz[x]++;

insert(x,ch[x][val[x]void find(int x,int d)

}void del(int x,int d)

pre=-1;

find_pre(tree[d].rt,d);

splay(t2,tree[d].rt);

int c=ch[tree[d].rt][1];

ch[t2][1]=c;fa[c]=t2;

fa[t2]=0;tree[d].rt=t2;

up(t2);

}int pos;

void change(int x,int d)

int mid=(tree[x].l+tree[x].r)>>1;

if(mid>=pos)change(x<<1,d);

else change(x<<1|1,d);

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

int l,r,p1;

int ask(int x)

int mid=(tree[x].l+tree[x].r)>>1;

int ans=0;

if(mid>=l) ans+=ask(x<<1);

if(mid1|1);

return ans;

}int s[20005],top;

int ans;

struct tree_arr

return ans;

}void change(int x)

}void insert_arr()

}arr;

bool cmp(int a,int b)

void lsh()

}int main()

lsh();

printf("%d\n",ans);

build(1,1,n);

scanf("%d",&m);

int x,y;

for(int i=1;i<=m;i++)

return

0;}

BZOJ2141 排隊(線段樹套Treap)

點此看題面 大致題意 給你乙個序列,每次交換兩個數,求每次操作後的逆序對個數。推薦先去看一下這道題目 洛谷3759 tjoi2017 不勤勞的圖書管理員 貌似是此題的公升級版 推薦先去學一學線段樹套 treap 當然你也可以學習 hl666 奆佬分塊狂踩樹套樹 做了上面給出的那道題目,這道題目就是一...

bzoj 2141 排隊 (樹狀陣列套線段樹)

題目大意 給出乙個序列,每次交換兩個位置的數,求交換完後整個序列的逆序對數。對於乙個位置會產生的逆序對數是他前面比他大的數 他後面比他小的數。我們可以用樹狀陣列套線段樹維護一下,外層表示位置在樹狀陣列中該點的控制區間,線段樹是權值線段樹。然後每次交換完了計算一下就可以了。include includ...

bzoj2141 排隊(線段樹 splay)

題目鏈結 分析 之所以找到這道題是因為不想寫dp了 看到網上的題解都是 分塊 線段樹,樹狀陣列 線段樹。立志自己想解法 一開始我在想,能不能用cdq搞 但是cdq版的動態逆序對好像是單點修改 實際上逆序對的個數就是每個數字形成的逆序對之和 而每個數會和在ta之前比ta大的數以及在ta之後比ta大的數...