日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线段树——单点更新(二)

發(fā)布時間:2025/4/14 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线段树——单点更新(二) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

HDU 4217 Data Structure??

http://acm.hdu.edu.cn/showproblem.php?pid=4217

CZ做的一道題目,我?guī)兔戳丝础?/p>

題意:給定N個數(shù)(1---N),K個操作,然后給K數(shù),i1,i2,i3.......ik 每次取走當(dāng)前狀態(tài)下等的第i個數(shù)(從小到大的),問取走的數(shù)的和。

給的那個的n為262144可以斷定肯定是O(n*log(n))級的算法,所以選定線段樹。

葉子節(jié)點賦值為1,這些節(jié)點存儲的就是數(shù)的個數(shù),在添加一個val數(shù)組記錄是哪個數(shù)。每次更新將節(jié)點a[rt]變成0,找出對應(yīng)的val[rt]即可。

這里坑爹的地方時sum求和時,要用—int64.wa了很多次才發(fā)現(xiàn)。

View Code #include <iostream> #include <cstring> #include <cstdio> #define maxn 262145 using namespace std;int a[maxn*4],val[maxn*4]; int tmp; __int64 sum;void pushup(int rt) {a[rt] = a[rt<<1] + a[rt<<1|1]; } void build(int l,int r,int rt) {if (l == r){a[rt] = 1;val[rt] = ++tmp;return ;}int m = (l + r)>>1;build(l,m,rt<<1);build(m + 1,r,rt<<1|1);pushup(rt); } void update(int sc,int l,int r,int rt) {if (l == r){a[rt] = 0;sum += val[rt];return ;}int m = (l + r)>>1;if (sc <= a[rt<<1]) update(sc,l,m,rt<<1);else{sc -= a[rt<<1];update(sc,m + 1,r,rt<<1|1);}pushup(rt); } int main() {int n,q,t,c;int cas = 1;scanf("%d",&t);while (t--){for (int i = 0; i < 4*maxn; ++i) a[i] = val[i] = 0;tmp = 0;scanf("%d%d",&n,&q);sum = 0;build(1,n,1);while (q--){scanf("%d",&c);update(c,1,n,1);}printf("Case %d: %I64d\n",cas++,sum);}return 0; }

?

?hdu 4263?Juggler

http://acm.hdu.edu.cn/showproblem.php?pid=4262

題意:

可以把本題理解成一個佛珠在手里轉(zhuǎn),可以順時針也可以逆時針,每次將手中的佛珠扣下來扔掉,給出每個佛珠扔出去的順序,每移動一個佛珠或者扔掉一個佛珠就要耗時1s最小耗時。

思路:

單純的模擬是O(n^2)的復(fù)雜度,肯定會超時,這里我們用線段樹來維護,葉子節(jié)點0/1表示該點是否被移除,當(dāng)訪問當(dāng)前點與要被刪除的點的相對位置時,我們用線段樹區(qū)間和來求,扔出后單點更新,訪問下一個到達(dá)手中的點時,getpos來求。這里主要是循環(huán)圈不好想。。傷腦筋。。

View Code #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string>#define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b)#define ll __int64 #define inf 0x7f7f7f7f #define MOD 1000000007ll #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100010 #define N 1000005 #define M 200007 using namespace std;int val[maxn<<2]; int pos[maxn];void pushup(int rt) {val[rt] = val[rt<<1] + val[rt<<1|1]; } void build(int l,int r,int rt) {if (l == r){val[rt] = 1;return ;}int m = (l + r)>>1;build(lc);build(rc);pushup(rt); } void update(int pos,int l,int r,int rt) {if (l == r){val[rt] = 0;return ;}int m = (l + r)>>1;if (pos <= m) update(pos,lc);else update(pos,rc);pushup(rt); } int query(int L,int R,int l,int r,int rt) {if (l >= L && r <= R) return val[rt];int res = 0;int m = (l + r)>>1;if (L <= m) res += query(L,R,lc);if (R > m) res += query(L,R,rc);return res; } int getpos(int s,int l,int r,int rt) {if (l == r) return l;int m = (l + r)>>1;if (s <= val[rt<<1]) return getpos(s,lc);else{s -= val[rt<<1];return getpos(s,rc);} } int main() {//freopen("din.txt","r",stdin);int n,i,a;while (~scanf("%d",&n)){if (!n) break;for (i = 1; i <= n; ++i){scanf("%d",&a);pos[a] = i;//標(biāo)記第a個被扔出去的編號 }build(1,n,1);int curpos = 1;//當(dāng)前在手中的點的標(biāo)號ll ans = 0;for (i = 1; i <= n; ++i){int tmp = 0;if (curpos == pos[i]) ans += 1;//只剩一個點了else if (curpos < pos[i])//1 2 3 4 5; 3要被刪除 {tmp = query(curpos + 1,pos[i],1,n,1);ans += (min(tmp,n - i + 1 - tmp) + 1);//n - i + 1 - tmp就是順時針的個數(shù)了,這里比賽時寫麻煩了 }else//同理 {tmp = query(pos[i],curpos - 1,1,n,1);ans += (min(tmp,n - i + 1 - tmp) + 1);}//printf(">>%d %d %d %d\n",tmp,n - i + 1 - tmp,Min(tmp,n - i + 1 - tmp),(Min(tmp,n - i + 1 - tmp) + 1));//這里發(fā)現(xiàn)了用宏定義的Min不行出錯update(pos[i],1,n,1);int s = query(1,pos[i],1,n,1);if (s < n - i)//如果pos[i]后面還有未被刪除的點curpos = getpos(s + 1,1,n,1);else//如果沒有就找第一個未被刪除的點curpos = getpos(1,1,n,1);}printf("%I64d\n",ans);}return 0; }

?1006 hdu 4325?http://acm.hdu.edu.cn/showproblem.php?pid=4325

http://www.cnblogs.com/E-star/archive/2012/08/01/2619066.html

pku?Sliding Window?http://poj.org/problem?id=2823

題解:http://www.cnblogs.com/E-star/archive/2012/08/26/2657596.html

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/E-star/archive/2012/07/22/2603493.html

總結(jié)

以上是生活随笔為你收集整理的线段树——单点更新(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。