1. 程式人生 > >震驚!Vector兩行程式碼求逆序對,六行程式碼過普通平衡樹

震驚!Vector兩行程式碼求逆序對,六行程式碼過普通平衡樹

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1e6+10;
const int maxn=0x7fffff;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char
c=nc();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();} return x*f; } #define root tree[0].ch[1] struct node { int v,fa,ch[2],rec,sum; }; node tree[MAXN]; int pointnum,tot; int iden(int x){return tree[tree[x].fa].ch[0
]==x?0:1;} inline void connect(int x,int fa,int how){tree[x].fa=fa;tree[fa].ch[how]=x;} inline void update(int x){tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;} inline void rotate(int x) { int y=tree[x].fa; int R=tree[y].fa; int Rson=iden(y); int yson=iden(x);
int b=tree[x].ch[yson^1]; connect(b,y,yson); connect(y,x,yson^1); connect(x,R,Rson); update(y);update(x); } void splay(int pos,int to)// 把編號為pos的節點旋轉到編號為to的節點 { to=tree[to].fa; while(tree[pos].fa!=to) { if(tree[tree[pos].fa].fa==to) rotate(pos); else if(iden(tree[pos].fa)==iden(pos)) rotate(tree[pos].fa),rotate(pos); else rotate(pos),rotate(pos); } } inline int newpoint(int v,int fa)// { tree[++tot].fa=fa; tree[tot].v=v; tree[tot].sum=tree[tot].rec=1; return tot; } inline void dele(int x) { tree[x].ch[0]=tree[x].ch[1]=0; if(x==tot) tot--; } int find(int v) { int now=root; while(1) { if(tree[now].v==v) {splay(now,root);return now;} int nxt=v<tree[now].v?0:1; if(!tree[now].ch[nxt])return 0; now=tree[now].ch[nxt]; } } int build(int v) { pointnum++; if(tot==0){root=1;newpoint(v,0);} else { int now=root; while(1) { tree[now].sum++; if(tree[now].v==v){tree[now].rec++;return now;}//出現過 int nxt=v<tree[now].v?0:1; if(!tree[now].ch[nxt]) { newpoint(v,now); tree[now].ch[nxt]=tot; return tot; } now=tree[now].ch[nxt]; } } return 0; } inline void insert(int v) { int p=build(v);//p代表插到了哪裡 splay(p,root); } void pop(int v) { int deal=find(v); if(!deal) return ; pointnum--; if(tree[deal].rec>1){tree[deal].rec--;tree[deal].sum--;return ;} if(!tree[deal].ch[0]) root=tree[deal].ch[1],tree[root].fa=0; else { int le=tree[deal].ch[0]; while(tree[le].ch[1]) le=tree[le].ch[1]; splay(le,tree[deal].ch[0]); int ri=tree[deal].ch[1]; connect(ri,le,1);connect(le,0,1); update(le); } dele(deal); } int rank(int v)// 查詢值為v的數的排名 { int ans=0,now=root; while(1) { if(tree[now].v==v) return ans+tree[tree[now].ch[0]].sum+1; if(now==0) return 0; if(v<tree[now].v) now=tree[now].ch[0]; else ans+=tree[tree[now].ch[0]].sum+tree[now].rec,now=tree[now].ch[1]; } if(now) splay(now,root); return 0; } int arank(int x)//查詢排名為x的數是什麼 { int now=root; while(1) { int used=tree[now].sum-tree[tree[now].ch[1]].sum; if(x>tree[tree[now].ch[0]].sum&&x<=used) break; if(x<used) now=tree[now].ch[0]; else x=x-used,now=tree[now].ch[1]; } splay(now,root); return tree[now].v; } int lower(int v)// 小於v的最大值 { int now=root; int ans=-maxn; while(now) { if(tree[now].v<v&&tree[now].v>ans) ans=tree[now].v; if(v>tree[now].v) now=tree[now].ch[1]; else now=tree[now].ch[0]; } return ans; } int upper(int v) { int now=root; int ans=maxn; while(now) { if(tree[now].v>v&&tree[now].v<ans) ans=tree[now].v; if(v<tree[now].v) now=tree[now].ch[0]; else now=tree[now].ch[1]; } return ans; } int a[MAXN],n,ans=0; int main() { #ifdef WIN32 freopen("a.in","r",stdin); #else #endif n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) { insert(a[i]); int now=rank(a[i]); if(i==1) continue; ans=ans+i-now; } printf("%d",ans); }

相關推薦

震驚Vector程式碼程式碼普通平衡

#include<iostream> #include<cstdio> using namespace std; const int MAXN=1e6+10; const int maxn=0x7fffff; inline char nc() { static

震驚Vector代碼代碼普通平衡

參考 div amp spa cor clas sin 考試 main Vector兩行代碼求逆序對 背景:濟南集訓Day7上午T2,出了一道逆序對的裸題,SB的我沒看出是逆序對來,於是現場推了一個很刁鉆的求逆序對的方法 首先我們想一下冒泡排序的過程,我們不難發

spl ans stream oid close algo ostream nbsp span 方法一:樹狀數組 模板如下: #include<iostream> #include<cstdio> #include <algorithm&g

1688

題目 codevs ger sample -i icon 逆序 -h else codevs——1688 求逆序對 前面剛剛說了逆序對,那就先那個題來練練手吧。。。(雖然是個板子(⊙o⊙)…) 時間限制:

洛谷P1521 題解

-i can 由於 逆序 family std sum 16px div 題意:   求1到n的全排列中有m對逆序對的方案數。 思路:   1.f[i][j]表示1到i的全排列中有j對逆序對的方案數。   2.顯然,1到i的全排列最多有(i-1)*i/2對逆序對,而對於

[Codevs] 1688

dev close wrapper pro lld cti none des put 1688 求逆序對 時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題目描

狀數組

res gets 逆序 算法 fps string ons 基本 -a 我們知道,求逆序對最典型的方法就是歸並排序,但是還有一種方法就是樹狀數組。假如你理解了樹狀數組,樹狀數組求逆序對相比歸並排序排序要更好理解一些,而且樹狀數組的代碼量也要少一些。 我們先看一下逆序對是什麽

Codevs 1688 (權值線段

per wrapper oid tdi nod 時間限制 cti 一個 sca 1688 求逆序對 時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題解 查看運行結

【歸並排序

div closed spa main sed pri 歸並 逆序對 con 【AC】 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 co

POJ2299 狀數組

include poj pre spa ans unique urn void algo 裸題,不多解釋。 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm

線段

std con pac clu can -m cnblogs amp ons 思路: 離散化變成一個1-n的數組表示每個數的排名,然後按順序插入各個數排名,並且查詢比它排名大的數的個數。 這個離散化方法還是比較好的,思維難度和代碼難度都比較小。 #include <

Another Version of Inversion 二維狀數組

return TP span namespace 關於 max using ble oid Another Version of Inversion 題意:只有2種走路方式,往右或者往下,求先走到一個大的數,在走到小的數的這種方式有多少。也就是說求出關於這個2維矩陣的逆序數

nlogn&&陌上花開

www 計數器 比較 stk cst 運用 完成後 spa 數組 前置: nlogn逆序對: 前一個小時我還真的不會這個Orz 這裏運用歸並排序的思想。 對於一個序列,我們把它先分開,再合並成一個有序序列。 引自https://blog.csdn.net/qq_301892

[USACO17FEB] Why Did the Cow Cross the Road I P (狀數組 易錯題)

-h 特殊性 另一個 %d .org class data 操作 efi 題目大意:給你兩個序列,可以序列進行若幹次旋轉操作(兩個都可以轉),對兩個序列相同權值的地方連邊,求最少的交點數 記錄某個值在第一個序列的位置,再記錄第二個序列中某個值 在第一個序列出現的位置 ,求逆

淺談狀數組

nlog 不變 for i++ 需要 逆序對 date 縮小 math 做了一道樹上求逆序對的題,主要難點並不在於樹形結構,而是求逆序對數。(在我看來是這樣的)。 to洛谷P3605晉升者計數。 發現自己樹狀數組求逆序對還有個坑,先填上再說。再加上最近學的樹狀數組離散化,捋

離散化及狀陣列

用樹狀陣列求逆序對的時候注意:要統計b[i]-1的字首和,因為可能有相同值的元素 不去重離散化: sort(a+1, a+n+1, cmp); for(int i=1; i<=n; i++) { if(i == 1 || a[i].val != a[i-1].val) { to

HDU 5592 ZYB's Premutation (線段)

題意 給你一組從1到n的排列,表示的是你當前所擁有的逆序對數,現在讓你重新還原這個排列。 思路 我們知道 [1⋅⋅⋅i] [ 1 ·

【模板】歸併排序

歸併排序求逆序對 1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 6 typedef long lon

bzoj2431 || 洛谷P1521

考慮一下插⼊法 n &lt; = 10

【模板】歸併排序(+

沒有網址qwq 沒有oj 翻樹狀陣列看到求逆序對先複習一下歸併求逆序對qwq 逆序對真是個神奇的東西啊QAQ 純屬隨手一打隨手一貼quq 1 #include<cstdio> 2 #include<iostream> 3 using namespace std