hdu 2430 線段樹維護下標

2022-05-24 10:51:08 字數 1338 閱讀 2431

求一段連續的區間,使其在滿足 和 對p取餘不超過k的 前提 下 和最大 。

做法:用線段樹維護區間最小值,最小的下標,即最左邊,因為加入sum[i]%p>k就要減去乙個sum[id]   ,  sum[id]%p在【sum[i]%p-k,sum[i]%p】之間,

sum[i]-sum[id]的值就為以i結尾的滿足條件的連續的一段數的最大值,所以id要盡可能小,所以就是求值在【sum[i]%p-k,sum[i]%p】之間的最左邊的數的下標,即滿足條件的數的下標最小值。

每次更新時把進過的結點的下標最小值(如果能更新)都更新一遍

view code

#include

#include

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

const

int inf = 1000000000;

const

int maxn = 1000010;

__int64 sum[maxn];

int min[maxn<<2];

int min(int a,int b)

int update(int num,int id,int l,int r,int rt)

int m=(l+r)>>1;

int a;

if(num<=m) a=update(num,id,lson);

if(num>m) a=update(num,id,rson);

if(min[rt]>a) min[rt]=a;

return min[rt];

}int query(int l,int r,int l,int r,int rt)

int m=(l+r)>>1;

int ret=inf;

if(l<=m) ret=min(ret,query(l,r,lson));

if(r>m) ret=min(ret,query(l,r,rson));

return ret;

}int main()

build(0,p-1,1);

update(0,0,0,p-1,1);

int id=0;

int ans=-1;

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

update(sum[i]%p,i,0,p-1,1);

}if(ans==-1)

printf("

case %d: %d\n

",ca++,-1);

else printf("

case %d: %d\n

",ca++,ans);

}return

0;}

hdu2430 單調佇列

這題用單調佇列需要分析好,當然也是自己思維不靈活,老想套用其他題的方法。題意 求出字串和,使其滿足sum p k使sum p最大 單調佇列,自己理解主要在於每次更新操作覆蓋掉無用的部分,即根據單調關係那部分在以後的判斷都是無用的那一部分,從而使效率提高,而不要盲目的去退隊從而將有用的部分去掉使答案錯...

hdu4288 線段樹維護多個sum

題意 給n個有序的數字,三個操作 1 刪除數字x 2 增加數字x 3 求i 5 3的數字之和 i為數字的下標 思路 一開始想水一下,結果超時。先對所有輸入的數字離散化,線段樹維護區間上點的個數和5個sum值,區間合併的時候要注意 左兒子節點和父親節點的關係很容易,右兒子合併的時候與左兒子中的點個數有...

線段樹 維護序列

老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為 n 的數列,不妨設為 a1,a2,an。有如下三種操作形式 把數列中的一段數全部乘乙個值 把數列中的一段數全部加乙個值 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模 p 的值。輸入格式 第一行兩個整數 n 和 p ...