求一段連續的區間,使其在滿足 和 對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 ...