傳送門
若題目是詢問區間是否有過半眾數,就是主席樹,按值域建樹,不斷判斷左右子樹子節點數量大於(r-l+1)/2,如果一直可以到葉子節點,則return true,否則return false
若題目是詢問區間是否有過半眾數且帶修改,就是樹套樹(雖然我還沒打過樹套樹)
那我們可以考慮分塊做法,n<=40000,是符合o(n√n)的
思考:對於乙個區間,這個區間存在兩種情況
1.[l,r]都由整塊構成
2.[l,r]由整塊和一些零散的點構成
我們可以預處理出這樣的兩個陣列
sum[i][j]從最開始到第i塊j這種顏色出現的次數,p[i][j]第i塊到第j塊的眾數
處理p陣列時有乙個小技巧,保證時間
我原來的處理是這樣的
for(int i=1;i<=num;++i)tle會tfor(int j=i;j<=num;++j)
p[i][j]=col;
}
然後我們可以這樣打
for(int i=1;i<=num;++i)rightfor(int j=l[i];j<=n;++j)tong[a[j]]=0
; }
每一次在統計的時候,先找到整塊的眾數,前後的殘餘的點開乙個桶暴力判斷即可(每一次桶記得清空)
記得離散化
**~
#include#define inf 2100000001蒲公英#define n 40003
#define ll long long
using
namespace
std;
intread()
while(s>='
0'&&s<='9')
return x*f;}//
sum[i][j]從最開始到第i塊j這種顏色出現的次數,p[i][j]第i塊到第j塊的眾數,id[i]i所在的塊
intn,m,num,pp;
int a[n],b[n],l[202],r[202],id[n],color[n],tong[n],ans[50003
];int ge[202][202],p[202][202],sum[202
][n];
void
init()
num=i;
}num++;
l[num]=base*(num-1)+1;r[num]=n;
for(int j=l[num];j<=r[num];++j)id[j]=num,sum[num][a[j]]++;//
單純分塊,最後一塊單獨處理
for(int i=1;i<=num;++i)
for(int j=1;j<=pp;++j)
sum[i][j]+=sum[i-1][j];//
字首和處理sum
for(int i=1;i<=num;++i)
for(int j=l[i];j<=n;++j)tong[a[j]]=0
; }
}int query(int l,int
r)
return
answer;
}int answer=p[pos1+1][pos2-1];//
先取出整塊的眾數
int tot=sum[pos2-1][answer]-sum[pos1][answer];
int x=l,y=l[pos1+1]-1;//
前面殘餘的
for(int i=x;i<=y;++i)
x=l[pos2],y=r;//
後面殘餘的
for(int i=x;i<=y;++i)
return
answer;
}int
main()
init();
for(int i=1;i<=m;++i)
}
洛谷P4168 蒲公英 分塊
給出乙個長度為n n的序列,m m次詢問,求區間 l,r l r 以下內容參考lyd lyd 演算法競賽高階指南 先離散化不解釋。分塊演算法一般都是以 暴力 區間預處理 暴力 的方法做的。所以,我們把n n分成t t塊,每塊長度 tn nt 然後預處理出對於任意兩個區間內的數字個數。也就是說,對於任...
洛谷P4168 Violet 蒲公英 分塊
時空限制 2000ms 512mb 題目描述 在鄉下的小路旁種著許多蒲公英,而我們的問題正是與這些蒲公英有關。為了簡化起見,我們把所有的蒲公英看成乙個長度為n的序列 a 1,a 2 a n 其中ai為乙個正整數,表示第i棵蒲公英的種類編號。而每次詢問乙個區間 l,r 你需要回答區間裡出現次數最多的是...
P4168 Violet 蒲公英 分塊
題目鏈結 分塊。p i j 表示第 i 個塊到第 j 個塊內的眾數,預處理出來就好了,列舉 i 和 j 是 o sqrt n 的,列舉 j 塊內的數也是 o sqrt n 的,總複雜度 o n sqrt n sum i h 表示前 i 個塊數字 h 出現的個數,預處理是 o n 的。對於每乙個查詢,...