bzoj 2120 數顏色 (分塊做法)

2021-08-21 20:50:26 字數 2164 閱讀 5190

此篇文章主要講修改操作

用pre[i]表示第i個元素的前乙個相同元素的位置,問題變成在區間[l,r]裡找大於l的數的個數,

(具體什麼意思去其他地方看)預設值為最大值。

用ppp[i]表示顏色i最後出現的位置(針對這道題顏色最多1e6種,建乙個1e6的陣列即可)

color[i]表示第i個位置是什麼顏色

總個數為n

這個是color陣列

修改操作的主要問題是如何在序列後找到修改之前的顏色的第乙個位置

修改之後的顏色前乙個位置,後乙個位置

這裡就要用到ppp陣列解決這個問題

上圖下面的那個陣列是ppp陣列

比如將5號位置的3修改為2

那麼我們要更改值的位置則為五號位置後面的32

問題就是如何尋找顏色2,3

很簡單,如圖這是乙個鏈式結構,只要我們從ppp陣列中找到相應元素的最後位置,在通過pre陣列的值往前找就可以了

沿棕色的線尋找3

沿紅色的線尋找2

找到位置改值再對相應的塊進行重構修改就完成了。注意維護ppp陣列的值始終保持為最後乙個元素值

#include

#include

#include

#include

#define inf 0x3f3f3f3f

using namespace std;

int a[205][205];

int pre[200005];

int color[200005];

int ppp[1000005];

int n,m,l,r;

void reset(intx)

sort(a[p]+1,a[p]+l+1);

}void build()

sort(a[i]+1,a[i]+l+1);

}}int search(int

x,int

y) for(int i=x;i<=p*l;i++)

if(pre[i]

ans++;

for(int i=q

*l+1;i<=y;i++)

if(pre[i]

ans++;

for(int i=p;i

return ans;

}void change(int

x,int

y)//位置x,顏色y.

else

c=ppp[y];

if(c

else

if(pre[c]

else

pre[x]=pre[c];

pre[c]=x;

reset(x);

reset(c);

}} int main()

l=floor(sqrt(n));

if(n%l>0)

r=n/l+1;

else

r=n/l;

build();

/*printf("%d %dff\n",l,r);

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

printf("%d ",pre[i]);

puts("");*/

intx,y;

char c[10];

for(int i=0;i

return

0;}

bzoj2120 數顏色 分塊

據說暴力可過2200ms。然而我寫分塊也才1200ms。然而很多人寫分塊跑不過暴力。參考了將狼踩盡 的思路。假設分為m塊 注意不是每塊m個 用sum x y z 表示在塊x y中顏色z 經過離散化以後 的個數,val x y 表示在x y塊中不同顏色的個數。這樣應該就比較容易明白了。修改 看u會影響...

BZOJ 2120 數顏色 分塊

time limit 6 sec memory limit 259 mb submit 6031 solved 2392 submit status discuss 墨墨購買了一套n支彩色畫筆 其中有些顏色可能相同 擺成一排,你需要回答墨墨的提問。墨墨會像你發布如下指令 1 q l r代表詢問你從第...

BZOJ 2120 數顏色 莫隊

題目傳送門 觀察前兩題,莫隊演算法好像是一種只支援查詢的離線演算法,但是莫隊真的不支援修改嗎?答案當然是否定的 莫隊是一種支援查詢和修改的離線演算法。就是一種優美的暴力 考慮在莫隊演算法中增加乙個變數no w 表示當前有no w 個修改已經修改掉了。並在每乙個詢問中增加乙個變數pr e 表示最近的修...