2016北京集訓試題17 陣列 線段樹

2022-05-03 18:12:08 字數 1464 閱讀 8032

線段樹亂搞orz。

定義pre[i]為從i點往前找到第1個顏色和點i相同的點。樹狀陣列記錄max和sum。max記錄區間[l,r]內pre的最大值,sum記錄區間[l,r]內的答案總和。注意:最終的答案是取

$n*(n+1)/2-\sum _^max(pre[i],1\leq i\leq r)$,即列舉所有子區間的右節點,找最左的左節點。因此,sum[x](記錄區間[l,r])在更新的時候,sum[x的左節點]可以直接加上,而對於x的右節點要保證區間[mid+1,r]的數和max[x的左節點]取最大值。這個可以在log(n)內搞定。

然後。。就ok了。

我怕是學了個假的線段樹。

#include#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const

int n=1e5+10

;int

n,m;

intcol[n],pre[n];

setid[n];

ll sum[n

<<2],mx[n<<2

];ll solve(

int k,int l,int

r,ll x)

void pushup(int k,int mid,int

r)void modify(int k,int l,int r,int x,int

y)

int mid=(l+r)/2

;

if (x<=mid) modify(k<<1,l,mid,x,y);else modify(k<<1|1,mid+1

,r,x,y);

pushup(k,mid,r);

}void build(int k,int l,int

r)

int mid=(l+r)/2

; build(k

<<1,l,mid);build(k<<1|1,mid+1

,r);

pushup(k,mid,r);

}set

::iterator q,l,r;

intx,to;

intmain()

build(

1,1,n);

intq,opt;

scanf("%d

",&q);

while (q--)

id[col[x]].erase(q);

col[x]=to;id[to].insert(x);

q=id[to].find(x);

l=r=q;l--;r++;

if (r!=id[to].end())

pre[x]=*l;

modify(

1,1,n,x,*l);}}

}

2016北京集訓 陣列

portal broken qwq 給你乙個陣列,每個元素有乙個顏色,要求支援兩種操作 1 修改某個元素的顏色 2 詢問這個陣列有多少個自取件內沒有重複的顏色 資料範圍 n 10 5,m 2n 顏色大小在 1 sim n 之間 這題。本來應該是乙個樹套樹題 但是為什麼一定要用樹套樹呢對吧qwq 首先...

(2016北京集訓十四) xsy1557 task

限制可以看成圖狀結構,每個任務的對物品數量的影響可以看成權值,只不過這個權值用乙個五元組來表示。那麼題意要求的就是最大權閉合子圖,網路流經典應用。1 include2 include3 include4 include5 include6 include7 define inf 1000000000...

xsy1531 北京集訓2016 魔法遊戲

orz sjk 有一棵樹,兩個人每個節點上有乙個權值,兩個人輪流選擇乙個根節點將其權值 k 除以 2,k 1 若除到 0 就刪去此根節點,它的兒子變成新根節點,刪掉最後乙個點贏。求先手還是後手必勝。首先考慮一些只有乙個根節點的樹,如果以二進位制角度看,每次除以 2,k 1 的數相當於拿掉一些二進位制...