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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ACM入门之【线段树习题】

發布時間:2025/3/20 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACM入门之【线段树习题】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 1275. 最大數【單點修改 區間最大】
  • 245. 你能回答這些問題嗎【單點修改 / 區間內的最大連續字段】
  • 246. 區間最大公約數【區間修改 區間最大公約數】
  • P3372 【模板】線段樹 1【區間修改,區間查詢】
  • P2574 XOR的藝術【區間求1的個數 區間取反】
  • 247. 亞特蘭蒂斯【掃描線 求矩陣的面積】

1275. 最大數【單點修改 區間最大】

#include<bits/stdc++.h> using namespace std; const int N=1e5*2+10; struct node{int l,r,v;}tr[N*4]; int m,p; void build(int u,int l,int r)//建樹 {tr[u]={l,r};if(l==r) return;int mid=tr[u].l+tr[u].r>>1;build(u*2,l,mid);build(u*2+1,mid+1,r); } void pushup(int u) {tr[u].v=max(tr[u*2].v,tr[u*2+1].v); } int query(int u,int l,int r) {if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v;//包含else{int v=0,mid=(tr[u].l+tr[u].r)/2;if(l<=mid) v=max(v,query(u*2,l,r));//左邊有交集if(r>=mid+1) v=max(v,query(u*2+1,l,r));//右邊有交集return v;} } void modify(int u,int x,int v) //u是根,x是位置,v是值 {if(tr[u].l==x&&tr[u].r==x) tr[u].v=v;//葉子else{int mid=tr[u].l+tr[u].r>>1;if(x<=mid) modify(u*2,x,v);else modify(u*2+1,x,v);pushup(u);} } int main(void) {cin>>m>>p;build(1,1,m);int last=0,n=0;for(int i=0;i<m;i++){char op; cin>>op;if(op=='Q'){int x; cin>>x;last=query(1,n-x+1,n);cout<<last<<endl;}else{int x; cin>>x;modify(1,n+1,(1ll*x+last)%p);n++;}}return 0; }

245. 你能回答這些問題嗎【單點修改 / 區間內的最大連續字段】

#include<bits/stdc++.h> using namespace std; const int N=1e5*5+10; struct node {int l,r;int sum,tmax,lmax,rmax;//sum: 區間和//tmax:整個區間的最大子段和//lmax:從左端點起的向右的最大子段和//rmax:從右端點起的向左的最大子段和 }tr[N*4]; int a[N],n,m; void push(node& a,node& l,node& r) {a.sum=l.sum+r.sum;a.tmax=max({l.tmax,r.tmax,l.rmax+r.lmax,l.sum+r.lmax,r.sum+l.rmax,});a.lmax=max({l.lmax,l.sum+r.lmax});a.rmax=max({r.rmax,r.sum+l.rmax}); } void pushup(int u) {push(tr[u],tr[u*2],tr[u*2+1]); } void build(int u,int l,int r) {if(l==r) tr[u]={l,r,a[l],a[l],a[l],a[l]};else{tr[u]={l,r};int mid=l+r>>1;build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);} } void modify(int u,int x,int v) {if(tr[u].l==x&&tr[u].r==x) {tr[u]={x,x,v,v,v,v};}else{int mid=(tr[u].l+tr[u].r)/2;if(mid>=x) modify(u*2,x,v);else modify(u*2+1,x,v);pushup(u);} } node query(int u,int l,int r) {if(l<=tr[u].l&&tr[u].r<=r) return tr[u];else {int mid=(tr[u].l+tr[u].r)/2;if(mid>=r) return query(u*2,l,r);else if(l>mid) return query(u*2+1,l,r);else{auto left=query(u*2,l,r);auto right=query(u*2+1,l,r);node res;push(res,left,right);return res;}} } int main(void) {cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=0;i<m;i++){int op,x,y; cin>>op>>x>>y;if(op==1){if(x>y) swap(x,y);auto temp=query(1,x,y);cout<<temp.tmax<<endl;}else modify(1,x,y);}return 0; }

246. 區間最大公約數【區間修改 區間最大公約數】



上述題解的原處

#include<bits/stdc++.h> using namespace std; typedef long long int LL; const int N=1e5*5+10; LL gcd(LL a,LL b){return b?gcd(b,a%b):a;} struct node {int l,r;LL sum,d;//sum區間總和,d區間最大公約數 }tr[N*4]; LL n,m,a[N]; void push(node& u,node& l,node& r) {u.sum=l.sum+r.sum;u.d=gcd(l.d,r.d); } void pushup(int u) {push(tr[u],tr[u*2],tr[u*2+1]); } void build(int u,int l,int r) {if(l==r){LL b=a[l]-a[l-1];tr[u]={l,r,b,b};}else{tr[u]={l,r};int mid=l+r>>1;build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);} } void modify(int u,int x,LL c) {if(tr[u].l==x&&tr[u].r==x){tr[u].sum+=c,tr[u].d+=c;return;}else{int mid=(tr[u].l+tr[u].r)/2;if(mid>=x) modify(u*2,x,c);else modify(u*2+1,x,c);pushup(u);} } node query(int u,int l,int r) {if(l<=tr[u].l&&tr[u].r<=r) return tr[u];else{int mid=(tr[u].l+tr[u].r)/2;if(mid>=r) return query(u*2,l,r);else if(l>=mid+1) return query(u*2+1,l,r);else{auto left=query(u*2,l,r);auto right=query(u*2+1,l,r);node res;push(res,left,right);return res;}} } int main(void) {cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=1;i<=m;i++){char op; cin>>op;if(op=='C'){LL l,r,d; cin>>l>>r>>d;modify(1,l,d);if(r+1<=n) modify(1,r+1,-d);}else{int l,r; cin>>l>>r;node right={0,0,0,0};auto left=query(1,1,l);if(l+1<=n) right=query(1,l+1,r);printf("%lld\n",labs(gcd(left.sum,right.d)));}}return 0; }

P3372 【模板】線段樹 1【區間修改,區間查詢】

#include<bits/stdc++.h> using namespace std; typedef long long int LL; const int N=1e5+10; struct node {int l,r;LL sum,add; }tr[N*4]; LL a[N],n,m; void pushup(int u) {tr[u].sum=tr[u*2].sum+tr[u*2+1].sum; } void pushdown(int u)//根節點更新,子結點 {auto &ans=tr[u];auto &l=tr[u*2];auto &r=tr[u*2+1];if(ans.add){l.sum+=(l.r-l.l+1)*ans.add;r.sum+=(r.r-r.l+1)*ans.add;l.add+=ans.add;r.add+=ans.add;ans.add=0;} } void build(int u,int l,int r) {if(l==r) tr[u]={l,r,a[l],0};else{int mid=(l+r)/2;tr[u]={l,r};build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);} } void modify(int u,int l,int r,int d) {if(l<=tr[u].l&&tr[u].r<=r){tr[u].sum+=1ll*(tr[u].r-tr[u].l+1)*d;tr[u].add+=d;}else{pushdown(u);int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) modify(u*2,l,r,d);if(r>=mid+1) modify(u*2+1,l,r,d);pushup(u);} } LL query(int u,int l,int r) {if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;else{pushdown(u);LL sum=0;int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) sum+=query(u*2,l,r);if(r>=mid+1) sum+=query(u*2+1,l,r);return sum;} } int main(void) {cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=0;i<m;i++){int op; cin>>op;if(op==1){int l,r,d; cin>>l>>r>>d;modify(1,l,r,d);}else{int l,r; cin>>l>>r;cout<<query(1,l,r)<<endl;}}return 0; }

P2574 XOR的藝術【區間求1的個數 區間取反】

#include<bits/stdc++.h> using namespace std; const int N=1e5*2+10; struct node {int l,r;int sum,add;//sum 1的個數 }tr[N*4]; int n,m,a[N]; char s[N]; void pushup(int u) {tr[u].sum=tr[u*2].sum+tr[u*2+1].sum; } void pushdown(int u) {if(tr[u].add) {tr[u*2].sum=(tr[u*2].r-tr[u*2].l+1)-tr[u*2].sum;tr[u*2+1].sum=(tr[u*2+1].r-tr[u*2+1].l+1)-tr[u*2+1].sum;tr[u*2].add^=1;tr[u*2+1].add^=1;tr[u].add=0; } } void build(int u,int l,int r) {if(l==r) tr[u]={l,r,a[l],0};else{tr[u]={l,r};int mid=(l+r)/2;build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);} } void modity(int u,int l,int r) {if(l<=tr[u].l&&tr[u].r<=r){tr[u].sum=(tr[u].r-tr[u].l+1)-tr[u].sum;tr[u].add^=1;}else{pushdown(u);int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) modity(u*2,l,r);if(r>=mid+1) modity(u*2+1,l,r);pushup(u);} } int query(int u,int l,int r) {if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;else{pushdown(u);int mid=(tr[u].l+tr[u].r)/2;int sum=0;if(l<=mid) sum+=query(u*2,l,r);if(r>=mid+1) sum+=query(u*2+1,l,r);return sum;} } int main(void) {cin>>n>>m;for(int i=1;i<=n;i++) cin>>s[i];for(int i=1;i<=n;i++) a[i]=s[i]-'0';build(1,1,n);for(int i=0;i<m;i++){int op,l,r; cin>>op>>l>>r;if(op==0) modity(1,l,r);else cout<<query(1,l,r)<<endl;}return 0; }

247. 亞特蘭蒂斯【掃描線 求矩陣的面積】

#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n; struct Segment {double x,y1,y2;bool operator< (const Segment &t)const{return x<t.x;}int k; }seg[N*2]; struct Node {int l,r;int cnt;//當前區間被覆蓋的次數double len;//子區間總共被覆蓋的長度 }tr[N*8]; vector<double>ys;int find(double y) {return lower_bound(ys.begin(),ys.end(),y)-ys.begin(); }void pushup(int u) {if(tr[u].cnt) tr[u].len=ys[tr[u].r+1]-ys[tr[u].l];else if(tr[u].l!=tr[u].r){tr[u].len=tr[u*2].len+tr[u*2+1].len; }else tr[u].len=0; }void build(int u,int l,int r) {tr[u]={l,r,0,0};if(l!=r){int mid=(l+r)/2;build(u*2,l,mid),build(u*2+1,mid+1,r);} }void modify(int u,int l,int r,int k) {if(l<=tr[u].l&&tr[u].r<=r){tr[u].cnt+=k;pushup(u);}else{int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) modify(u*2,l,r,k);if(r>mid) modify(u*2+1,l,r,k);pushup(u);} }int main() {int t=1;while(scanf("%d",&n),n){ys.clear();for(int i=0,j=0;i<n;i++){double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);seg[j++]={x1,y1,y2,1};seg[j++]={x2,y1,y2,-1};ys.push_back(y1),ys.push_back(y2);}sort(ys.begin(),ys.end());ys.erase(unique(ys.begin(),ys.end()),ys.end());build(1,0,ys.size()-2);sort(seg,seg+n*2);double res=0;for(int i=0;i<n*2;i++){if(i>0) res+=tr[1].len*(seg[i].x-seg[i-1].x);modify(1,find(seg[i].y1),find(seg[i].y2)-1,seg[i].k);}printf("Test case #%d\n",t++);printf("Total explored area: %.2lf\n\n", res);} }

總結

以上是生活随笔為你收集整理的ACM入门之【线段树习题】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。