atm參加了速算訓練班,經過刻苦修煉,對以2為底的對數算得飛快,人稱log大俠。
一天,log大俠的好友 drd 有一些整數序列需要變換,log大俠正好施展法力...
變換的規則是: 對其某個子串行的每個整數變為: [log_2 (x) + 1] 其中 表示向下取整,就是對每個數字求以2為底的對數,然後取下整。
例如對序列 3 4 2 操作一次後,這個序列會變成 2 3 2。
drd需要知道,每次這樣操作後,序列的和是多少。
【輸入格式】
第一行兩個正整數 n m 。
第二行 n 個數,表示整數序列,都是正數。
接下來 m 行,每行兩個數 l r 表示 atm 這次操作的是區間 [l, r],數列序號從1開始。
【輸出格式】
輸出 m 行,依次表示 atm 每做完乙個操作後,整個序列的和。
這題暴力肯定可以得一部分的,區間大小最差的情況就是每次都給l=1,r=n,這時暴力肯定不行的,會寫線段樹的話,可以看出這題也就是單點更新以及總區間查詢。而它沒說資料範圍,但就算是1e18的話,取log對於每個位置的數來說,它最多也就更新個60次左右,所以我們可以加個標記,代表這個區間內還有沒有位置需要更新,然後再線段樹維護,時間複雜度就是60*nlog(n)這樣。
1 #include2 #include3線段樹下線段果#define l(x) (x<<1)
4#define r(x) (x<<1|1)
5#define m(x) ((t[x].l+t[x].r)>>1)
6 typedef long
long
ll;7
const
int n=100118;8
struct
treet[n<<2
];13
ll a[n];
14void built(int id,int l,int
r)15
26built(l(id),l,m(id));
27 built(r(id),m(id)+1
,r);
28 t[id].flag=t[l(id)].flag|t[r(id)].flag;
29 t[id].sum=t[l(id)].sum+t[r(id)].sum;30}
31void modify(int id,int l,int
r)32
41if(l<=m(id))
42modify(l(id),l,r);
43if(r>m(id))
44modify(r(id),l,r);
45 t[id].flag=t[l(id)].flag|t[r(id)].flag;
46 t[id].sum=t[l(id)].sum+t[r(id)].sum;47}
48int
main()
4961
return0;
62 }
不懂線段樹的話,知道stl的map的話,還有種map的寫法,思路一樣,當某個位置的值<=2時就把它從map刪去。
1 #include2 #include3 #include4stlwdusing
namespace
std;
5 typedef long
long
ll;6 mapmmp;
7 map::iterator b,e,temp;
8int
main()918
while(m--)
1933 printf("
%lld\n
",sum);34}
35return0;
36 }
歷屆試題 log大俠
atm參加了速算訓練班,經過刻苦修煉,對以2為底的對數算得飛快,人稱log大俠。一天,log大俠的好友 drd 有一些整數序列需要變換,log大俠正好施展法力.變換的規則是 對其某個子串行的每個整數變為 log 2 x 1 其中 表示向下取整,就是對每個數字求以2為底的對數,然後取下整。例如對序列 ...
第五屆藍橋杯(國賽) Log大俠
問題描述 atm 參加了速算訓練班,經過刻苦修煉,對以 2 為底的對數算得飛快,人稱 log 大俠。一天,log 大俠的好友 drd 有一些整數序列需要變換,log 大俠正好施展法力 變換的規則是 對其某個子串行的每個整數變為 log2 x 1 其中 表示向下取整 就是對每個數字求以 2 為底的對數...
哪位大俠幫我看看
最近做乙個東西,就拿圖書管理打個比方吧。工具為 vc 資料庫為sql server,表一中放的是 借書的日期 以及 借多長時間 表二中放的是 提前多少天發郵件通知 表三中放的是 郵件接受人的郵箱位址 現在想做的功能 就是 1.在還書日期提前x天給借書人發郵件提醒 還書 2.同時給管理員發訊息,該給誰...