线段树题集
来源:互联网 发布:上位机编程用什么语言 编辑:程序博客网 时间:2024/05/17 18:19
POJ-2528
线段树的区间染色。如果直接离散化染色肯定会WA。
反例:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=1e4+7;int L[N],R[N],b[N<<2],f[N<<4],lz[N<<4],vis[N];void build(int rt,int l,int r){ lz[rt]=f[rt]=-1; if(l==r) return ; int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r);}inline void push_down(int rt){ if(lz[rt]!=-1) { lz[rt<<1]=lz[rt<<1|1]=f[rt<<1]=f[rt<<1|1]=lz[rt]; lz[rt]=-1; }}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { f[rt]=lz[rt]=v; return ; } int m=(l+r)>>1; push_down(rt); if(ql<=m) update(rt<<1,l,m,ql,qr,v); if(qr>m) update(rt<<1|1,m+1,r,ql,qr,v);}void query(int rt,int l,int r){ if(l==r) { if(f[rt]!=-1) vis[f[rt]]=true; return ; } push_down(rt); int m=(l+r)>>1; query(rt<<1,l,m); query(rt<<1|1,m+1,r);}int main(){ int T; scanf("%d",&T); while(T--) { int n,m=0; scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%d%d",&L[i],&R[i]); b[m++]=L[i];b[m++]=R[i]; b[m++]=L[i]-1;b[m++]=R[i]+1; } sort(b,b+m); m=unique(b,b+m)-b; memset(vis,0,sizeof(vis)); build(1,1,m); for(int i=0;i<n;++i) { L[i]=lower_bound(b,b+m,L[i])-b+1; R[i]=lower_bound(b,b+m,R[i])-b+1; update(1,1,m,L[i],R[i],i); } query(1,1,m); int ans=0; for(int i=0;i<n;++i) if(vis[i]) ++ans; printf("%d\n",ans); } return 0;}
POJ - 1177
扫描线求矩形并的轮廓长度。
矩形并的轮廓分为
#include<cstdio>#include<vector>#include<algorithm>using namespace std;const int N=2e4+7;struct Line{ int l,r,y,down; Line(int l,int r,int y,int down) : l(l),r(r),y(y),down(down) {} Line(){} bool operator < (const Line &r) const { return y<r.y; }};vector<Line> line;int L[N<<2],R[N<<2],c[N<<2],sum[N<<2],li[N<<2];void build(int rt,int l,int r){ L[rt]=R[rt]=c[rt]=sum[rt]=li[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r);}inline void push_down(int rt,int l,int r){ if(c[rt]!=-1) { int m=(l+r)>>1; c[rt<<1]=c[rt<<1|1]=c[rt]; sum[rt<<1]=(c[rt]?m-l+1:0); sum[rt<<1|1]=(c[rt]?r-m:0); L[rt<<1]=L[rt<<1|1]=R[rt<<1]=R[rt<<1|1]=(c[rt]>0); li[rt<<1]=li[rt<<1|1]=(c[rt]>0); }}inline void push_up(int rt){ c[rt]=(c[rt<<1]==c[rt<<1|1]&&c[rt<<1]!=-1?c[rt<<1]:-1); li[rt]=li[rt<<1]+li[rt<<1|1]-(R[rt<<1]&&L[rt<<1|1]); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; L[rt]=L[rt<<1];R[rt]=R[rt<<1|1];}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { if(c[rt]!=-1) { c[rt]+=v; sum[rt]=(c[rt]?r-l+1:0); li[rt]=L[rt]=R[rt]=(c[rt]>0); return ; } } push_down(rt,l,r); int m=(l+r)>>1; if(ql<=m) update(rt<<1,l,m,ql,qr,v); if(qr>m) update(rt<<1|1,m+1,r,ql,qr,v); push_up(rt);}int main(){ int n; while(~scanf("%d",&n)) { int N=20001; line.clear(); for(int i=0;i<n;++i) { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1+=10001;x2+=10001; line.push_back(Line(x1,x2,y1,1)); line.push_back(Line(x1,x2,y2,-1)); } sort(line.begin(),line.end()); build(1,1,N); int ny=line[0].y,ans=0,last=0; for(int i=0;i<line.size();++i) { ans+=li[1]*(line[i].y-ny)*2; update(1,1,N,line[i].l,line[i].r-1,line[i].down); ans+=abs(sum[1]-last); ny=line[i].y; last=sum[1]; } printf("%d\n",ans); } return 0;}
HDU - 4578
维护三个和,再维护
细节很多。。。容易写错。
#include<bits/stdc++.h>#define lson (rt<<1)#define rson (rt<<1|1)using namespace std;const int N=1e5+7,mod=1e4+7;int p1[N<<2],p2[N<<2],p3[N<<2],add[N<<2],mul[N<<2],e[N<<2];void build(int rt,int l,int r){ p1[rt]=p2[rt]=p3[rt]=add[rt]=0;e[rt]=-1;mul[rt]=1; if(l==r) return ; int m=(l+r)>>1; build(lson,l,m); build(rson,m+1,r);}inline void addop(int rt,int c,int l,int r){ int c2=c*c%mod,c3=c2%mod*c%mod; p3[rt]=(p3[rt]+3*p2[rt]*c+3*p1[rt]*c2+c3*(r-l+1))%mod; p2[rt]=(p2[rt]+2*p1[rt]*c+c2*(r-l+1))%mod; p1[rt]=(p1[rt]+c*(r-l+1))%mod; if(e[rt]==-1) add[rt]+=c; else e[rt]=(e[rt]+c)%mod;}inline void mulop(int rt,int c,int l,int r){ int c2=c*c%mod,c3=c2*c%mod; p3[rt]=p3[rt]*c3%mod; p2[rt]=p2[rt]*c2%mod; p1[rt]=p1[rt]*c%mod; if(e[rt]==-1) { add[rt]=add[rt]*c%mod; mul[rt]=mul[rt]*c%mod; } else e[rt]=e[rt]*c%mod;}inline void eop(int rt,int c,int l,int r){ int c2=c*c%mod,c3=c*c%mod*c%mod; p3[rt]=c3*(r-l+1)%mod; p2[rt]=c2*(r-l+1)%mod; p1[rt]=c*(r-l+1)%mod; add[rt]=0;mul[rt]=1; e[rt]=c;}inline void push_up(int rt){ p3[rt]=(p3[lson]+p3[rson])%mod; p2[rt]=(p2[lson]+p2[rson])%mod; p1[rt]=(p1[lson]+p1[rson])%mod;}inline void push_down(int rt,int l,int r){ if(e[rt]!=-1) { int m=(l+r)>>1; eop(lson,e[rt],l,m); eop(rson,e[rt],m+1,r); } else { int m=(l+r)>>1; mulop(lson,mul[rt],l,m); mulop(rson,mul[rt],m+1,r); addop(lson,add[rt],l,m); addop(rson,add[rt],m+1,r); } mul[rt]=1;add[rt]=0; e[rt]=-1;}void update(int rt,int l,int r,int ql,int qr,int op,int c){ if(ql<=l&&qr>=r) { if(op==1) addop(rt,c,l,r); else if(op==2) mulop(rt,c,l,r); else eop(rt,c,l,r); return ; } int m=(l+r)>>1; push_down(rt,l,r); if(ql<=m) update(rt<<1,l,m,ql,qr,op,c); if(qr>m) update(rt<<1|1,m+1,r,ql,qr,op,c); push_up(rt);}int query(int rt,int l,int r,int ql,int qr,int p){ if(ql<=l&&qr>=r) { if(p==1) return p1[rt]; else if(p==2) return p2[rt]; else if(p==3) return p3[rt]; } int m=(l+r)>>1; push_down(rt,l,r); int res=0; if(ql<=m) res+=query(lson,l,m,ql,qr,p); if(qr>m) res+=query(rson,m+1,r,ql,qr,p); return res%mod;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { if(n==0||m==0) break; build(1,1,n); while(m--) { int op,l,r,c; scanf("%d%d%d%d",&op,&l,&r,&c); if(op!=4) update(1,1,n,l,r,op,c); else printf("%d\n",query(1,1,n,l,r,c)); } } return 0;}
HDU - 1255
扫描线求矩形交面积,要求下边权
#include<bits/stdc++.h>using namespace std;typedef double ld;const int N=1007;struct Line{ int l,r,down; ld y; Line(int l,int r,ld y,int down) : l(l),r(r),y(y),down(down) {} Line(){} bool operator < (const Line & r) const { return y<r.y; }};ld b[N<<1],x1[N],y1[N],x2[N],y2[N],sum[N<<3],len[N<<1];vector<Line> line;int c[N<<3];void build(int rt,int l,int r){ c[rt]=sum[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r);}inline void push_down(int rt,int l,int r){ if(c[rt]!=-1) { c[rt<<1]=c[rt<<1|1]=c[rt]; int m=(l+r)>>1; sum[rt<<1]=c[rt]>=2?len[m]-len[l-1]:0; sum[rt<<1|1]=c[rt]>=2?len[r]-len[m]:0; }}inline void push_up(int rt){ c[rt]=(c[rt<<1]==c[rt<<1|1]&&c[rt<<1]!=-1?c[rt<<1]:-1) ; sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { if(c[rt]!=-1) { c[rt]+=v; sum[rt]=c[rt]>=2?len[r]-len[l-1]:0; return ; } } int m=(l+r)>>1; push_down(rt,l,r); if(ql<=m) update(rt<<1,l,m,ql,qr,v); if(qr>m) update(rt<<1|1,m+1,r,ql,qr,v); push_up(rt);}int main(){ int T; scanf("%d",&T); while(T--) { int n,m=0; scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%lf%lf%lf%lf",&x1[i],&y1[i],&x2[i],&y2[i]); b[m++]=x1[i];b[m++]=x2[i]; } sort(b,b+m); m=unique(b,b+m)-b; len[0]=0; for(int i=1;i<m;++i) len[i]=b[i]-b[i-1]+len[i-1]; --m; line.clear(); for(int i=0;i<n;++i) { int l=lower_bound(b,b+m,x1[i])-b+1; int r=lower_bound(b,b+m,x2[i])-b; line.push_back(Line(l,r,y1[i],1)); line.push_back(Line(l,r,y2[i],-1)); } sort(line.begin(),line.end()); build(1,1,m); ld ans=0; update(1,1,m,line[0].l,line[0].r,line[0].down); for(int i=1;i<line.size();++i) { ans+=sum[1]*(line[i].y-line[i-1].y); update(1,1,m,line[i].l,line[i].r,line[i].down); } printf("%.2f\n",ans); } return 0;}
HDU - 1394
直接套主席树就行了?
#include<bits/stdc++.h>using namespace std;const int N=5007;int tot,root[N*20],sum[N*20],ls[N*20],rs[N*20],a[N];void build(int &rt,int l,int r){ rt=++tot; sum[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(ls[rt],l,m); build(rs[rt],m+1,r);}void update(int& rt,int last,int l,int r,int p){ rt=++tot; ls[rt]=ls[last]; rs[rt]=rs[last]; sum[rt]=sum[last]+1; if(l==r) return ; int m=(l+r)>>1; if(p<=m) update(ls[rt],ls[last],l,m,p); else update(rs[rt],rs[last],m+1,r,p);}int query(int rt1,int rt2,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r) return sum[rt2]-sum[rt1]; int m=(l+r)>>1,res=0; if(ql<=m) res+=query(ls[rt1],ls[rt2],l,m,ql,qr); if(qr>m) res+=query(rs[rt1],rs[rt2],m+1,r,ql,qr); return res;}int main(){ int n; while(~scanf("%d",&n)) { tot=0; build(root[0],1,n); int ans=0; for(int i=1;i<=n;++i) { scanf("%d",&a[i]); ++a[i]; update(root[i],root[i-1],1,n,a[i]); ans+=query(root[0],root[i],1,n,a[i],n)-1; } int now=ans; for(int i=1;i<n;++i) { int ge=query(root[0],root[n],1,n,a[i],n); int le=query(root[0],root[n],1,n,1,a[i]); now=now-le+ge; ans=min(now,ans); } printf("%d\n",ans); } return 0;}
HDU - 5692
DFS序+线段树。
线段树维护每个点都根的距离。查询就查询其子树的最大值就行。
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<vector>#include<algorithm>#define lson (rt<<1)#define rson (rt<<1|1)using namespace std;const int N=1e5+7;typedef long long ll;ll c[N],d[N],mx[N<<2],lz[N<<2],tmp[N];int sz[N],tot,id[N];vector<int> adj[N];void dfs(int u,int p){ id[u]=++tot; sz[u]=1; for(int v: adj[u]) { if(v==p) continue; d[v]=d[u]+c[v]; dfs(v,u); sz[u]+=sz[v]; }}inline void push_up(int rt){ mx[rt]=max(mx[lson],mx[rson]);}void build(int rt,int l,int r){ lz[rt]=0; if(l==r) { mx[rt]=d[l]; return ; } int m=(l+r)>>1; build(lson,l,m); build(rson,m+1,r); push_up(rt);}inline void push_down(int rt){ if(lz[rt]) { lz[lson]+=lz[rt]; lz[rson]+=lz[rt]; mx[lson]+=lz[rt]; mx[rson]+=lz[rt]; lz[rt]=0; }}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { lz[rt] += v; mx[rt]+=v; return ; } int m=(l+r)>>1; push_down(rt); if(ql<=m) update(lson,l,m,ql,qr,v); if(qr>m) update(rson,m+1,r,ql,qr,v); push_up(rt);}ll query(int rt,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r) return mx[rt]; int m=(l+r)>>1; push_down(rt); if(ql>m) return query(rson,m+1,r,ql,qr); else if(qr<=m) return query(lson,l,m,ql,qr); else return max(query(rson,m+1,r,ql,qr),query(lson,l,m,ql,qr)); push_up(rt);}int main(){ int T; scanf("%d",&T); for(int kase=1;kase<=T;++kase) { int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;++i) adj[i].clear(); for(int i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v); ++u;++v; adj[u].push_back(v); adj[v].push_back(u); } for(int i=1;i<=n;++i) scanf("%I64d",&c[i]); d[1]=c[1]; tot=0; dfs(1,0); for(int i=1;i<=n;++i) tmp[id[i]]=d[i]; for(int i=1;i<=n;++i) d[i]=tmp[i]; build(1,1,n); printf("Case #%d:\n",kase); while(q--) { int op,u; scanf("%d%d",&op,&u); ++u; if(op) printf("%I64d\n",query(1,1,n,id[u],id[u]+sz[u]-1)); else { ll w; scanf("%I64d",&w); update(1,1,n,id[u],id[u]+sz[u]-1,w-c[u]); c[u]=w; } } } return 0;}
HDU - 3308
维护与左端点连续的LCIS的长度和与右端点连续的LCIS的长度和总区间LCIS的长度。
当合并区间时,若左子树的右端点小于右子树的左端点,中间的那段部分可能构成更长的LCIS,否则只需考虑左右子树的LCIS。
#include<bits/stdc++.h>#define lson (rt<<1)#define rson (rt<<1|1)using namespace std;const int N=1e5+7;int L[N<<2],R[N<<2],lenL[N<<2],lenR[N<<2],len[N<<2],a[N],ans;inline void push_up(int rt,int l,int r ){ int m=(l+r)>>1; len[rt]=max(len[lson],len[rson]); L[rt]=L[lson];R[rt]=R[rson]; lenL[rt]=lenL[lson];lenR[rt]=lenR[rson]; if(R[lson]<L[rson]) { len[rt]=max(len[rt],lenR[lson]+lenL[rson]); if(lenL[lson]==m-l+1) lenL[rt]+=lenL[rson]; if(lenR[rson]==r-m) lenR[rt]+=lenR[lson]; }}void build(int rt,int l,int r){ if(l==r) { L[rt]=R[rt]=a[l]; len[rt]=lenL[rt]=lenR[rt]=1; return ; } int m=(l+r)>>1; build(lson,l,m); build(rson,m+1,r); push_up(rt,l,r);}void update(int rt,int l,int r,int q,int v){ if(l==r) { L[rt]=R[rt]=v;a[l]=v; return ; } int m=(l+r)>>1; if(q<=m) update(lson,l,m,q,v); else update(rson,m+1,r,q,v); push_up(rt,l,r);}void query(int rt,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r) { ans=max(ans,len[rt]); return ; } int m=(l+r)>>1; if(qr<=m) query(lson,l,m,ql,qr); else if(ql>m) query(rson,m+1,r,ql,qr); else { query(lson,l,m,ql,qr); query(rson,m+1,r,ql,qr); if(R[lson]<L[rson]) ans=max(ans,min(lenR[lson],m-ql+1)+min(lenL[rson],qr-m)); } push_up(rt,l,r);}int main(){ int T; scanf("%d",&T); while(T--) { int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;++i) scanf("%d",&a[i]); build(1,1,n); char op[10]; while(q--) { int l,r; scanf("%s%d%d",op,&l,&r); if(op[0]=='Q') { ans=0; ++l;++r; query(1,1,n,l,r); printf("%d\n",ans); } else { ++l; update(1,1,n,l,r); } } } return 0;}
Codeforces-803G
动态开点线段树。。。。
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int N=1e5+7;int tot,ls[N*65],rs[N*65],mn[N*65],b[N],lz[N*65],dp[N][20],mm[N],n;void initRMQ(int n,int b[]){ mm[0]=-1; for(int i=1;i<=n;++i) { mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; dp[i][0]=b[i]; } for(int j=1;j<=mm[n];++j) for(int i=1;i+(1<<j)-1<=n;++i) dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}int rmq(int x,int y){ int k=mm[y-x+1]; return min(dp[x][k],dp[y-(1<<k)+1][k]);}int RMQ(int l,int r){ int lb=(l-1)/n,rb=(r-1)/n,lp=(l-1)%n+1,rp=(r-1)%n+1; if(lb==rb) return rmq(lp,rp); else if(lb+2<=rb||rp>=lp) return rmq(1,n); else return min(rmq(lp,n),rmq(1,rp));}int newnode(int l,int r){ ++tot; lz[tot]=ls[tot]=rs[tot]=0; mn[tot]=RMQ(l,r); return tot;}inline void push_down(int rt,int l,int r){ int m=(l+r)>>1; if(!ls[rt]) ls[rt]=newnode(l,m); if(!rs[rt]) rs[rt]=newnode(m+1,r); if(lz[rt]) { mn[ls[rt]]=mn[rs[rt]]=lz[ls[rt]]=lz[rs[rt]]=lz[rt]; lz[rt]=0; }}inline void push_up(int rt,int l,int r){ int m=(l+r)>>1; if(ls[rt]&&rs[rt]) mn[rt]=min(mn[ls[rt]],mn[rs[rt]]); else if(ls[rt]) mn[rt]=min(mn[ls[rt]],RMQ(m+1,r)); else if(rs[rt]) mn[rt]=min(mn[rs[rt]],RMQ(l,m));}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { mn[rt]=lz[rt]=v; return ; } push_down(rt,l,r); int m=(l+r)>>1; if(ql<=m) update(ls[rt],l,m,ql,qr,v); if(qr>m) update(rs[rt],m+1,r,ql,qr,v); push_up(rt,l,r);}int query(int rt,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r) return mn[rt]; push_down(rt,l,r); int m=(l+r)>>1; if(qr<=m) return query(ls[rt],l,m,ql,qr); else if(ql>m) return query(rs[rt],m+1,r,ql,qr); else return min(query(ls[rt],l,m,ql,qr),query(rs[rt],m+1,r,ql,qr)); push_up(rt,l,r);}int main(){ int k,q,L; scanf("%d%d",&n,&k); for(int i=1;i<=n;++i) scanf("%d",&b[i]); initRMQ(n,b); scanf("%d",&q); L=n*k; int rt=newnode(1,n); while(q--) { int op,l,r,x; scanf("%d%d%d",&op,&l,&r); if(op==1) { scanf("%d",&x); update(rt,1,L,l,r,x); } else printf("%d\n",query(rt,1,L,l,r)); } return 0;}
HDU - 3642
长方体交
将
这里求矩形交没用标
#include<bits/stdc++.h>#define lson (rt<<1)#define rson (rt<<1|1)using namespace std;typedef long long ll;const int N=2007;struct Cube{ int x1,x2,y1,y2,z1,z2;};struct Line{ int l,r,y,down; bool operator < (const Line & r) const { return y<r.y; }};vector<Cube> cube;vector<Line> line;int z[N],x[N],c[N<<2],len[N],len1[N<<2],len2[N<<2],sum[N<<2];void build(int rt,int l,int r){ len1[rt]=len2[rt]=c[rt]=sum[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(lson,l,m); build(rson,m+1,r);}inline void push_up(int rt,int l,int r){ if(l==r) { sum[rt]=len1[rt]=len2[rt]=0; if(c[rt]>=3) sum[rt]=len[r]-len[l-1]; else if(c[rt]==2) len2[rt]=len[r]-len[l-1]; else if(c[rt]==1) len1[rt]=len[r]-len[l-1]; } else if(c[rt]>=3) { sum[rt]=len[r]-len[l-1]; len1[rt]=len2[rt]=0; } else if(c[rt]==2) { sum[rt]=sum[lson]+sum[rson]+len2[lson]+len2[rson]+len1[lson]+len1[rson]; len2[rt]=len[r]-len[l-1]-sum[rt]; len1[rt]=0; } else if(c[rt]==1) { sum[rt]=sum[lson]+sum[rson]+len2[lson]+len2[rson]; len2[rt]=len1[lson]+len1[rson]; len1[rt]=len[r]-len[l-1]-sum[rt]-len2[rt]; } else { sum[rt]=sum[lson]+sum[rson]; len2[rt]=len2[lson]+len2[rson]; len1[rt]=len1[lson]+len1[rson]; }}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { c[rt]+=v; push_up(rt,l,r); return ; } int m=(l+r)>>1; if(ql<=m) update(lson,l,m,ql,qr,v); if(qr>m) update(rson,m+1,r,ql,qr,v); push_up(rt,l,r);}int main(){ int T; scanf("%d",&T); for(int kase=1;kase<=T;++kase) { int n,m=0,g=1; scanf("%d",&n); cube.clear(); for(int i=0;i<n;++i) { int x1,x2,y1,y2,z1,z2; scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2); cube.push_back({x1,x2,y1,y2,z1,z2}); z[m++]=z1;z[m++]=z2; x[g++]=x1;x[g++]=x2; } sort(z,z+m); sort(x,x+g); m=unique(z,z+m)-z; g=unique(x,x+g)-x; len[0]=0; for(int i=1;i<g;++i) len[i]=x[i]-x[i-1]+len[i-1]; --g; for(int i=0;i<n;++i) { cube[i].z1=lower_bound(z,z+m,cube[i].z1)-z; cube[i].z2=lower_bound(z,z+m,cube[i].z2)-z; cube[i].x1=lower_bound(x,x+g,cube[i].x1)-x+1; cube[i].x2=lower_bound(x,x+g,cube[i].x2)-x; } ll ans=0; for(int i=1;i<m;++i) { line.clear(); for(int j=0;j<n;++j) { if(cube[j].z2>=i&&cube[j].z1<=i-1) { line.push_back({cube[j].x1,cube[j].x2,cube[j].y1,1}); line.push_back({cube[j].x1,cube[j].x2,cube[j].y2,-1}); } } build(1,1,g); sort(line.begin(),line.end()); for(int j=0;j+1<line.size();++j) { update(1,1,g,line[j].l,line[j].r,line[j].down); ans+=(ll)sum[1]*(line[j+1].y-line[j].y)*(z[i]-z[i-1]); } } printf("Case %d: %I64d\n",kase,ans); } return 0;}
HDU-5634
因此一个区间如果不做修改,最多
因此我们可以直接搞一棵线段树就行了。
#include<bits/stdc++.h>#define lson (rt<<1)#define rson (rt<<1|1)using namespace std;typedef long long ll;const int P=1e7+7,N=3e5+7;ll phi[P],p[P];bool nop[P];void init(){ int c=0; phi[1]=1; for(int i=2;i<P;++i) { if(!nop[i]) { p[c++]=i; phi[i]=i-1; } for(int j=0;j<c&&i*p[j]<P;++j) { nop[i*p[j]]=true; if(i%p[j]==0) { phi[i*p[j]]=phi[i]*p[j]; break; } else phi[i*p[j]]=phi[i]*(p[j]-1); } }}ll sum[N<<2],a[N<<2];void push_up(int rt){ a[rt]=(a[lson]==a[rson]&&a[lson]!=-1)?a[lson]:-1; sum[rt]=sum[lson]+sum[rson];}void push_down(int rt,int l,int r){ if(a[rt]!=-1) { a[lson]=a[rson]=a[rt]; int m=(l+r)>>1; sum[lson]=a[rt]*(m-l+1); sum[rson]=a[rt]*(r-m); }}void build(int rt,int l,int r){ if(l==r) { scanf("%I64d",&a[rt]); sum[rt]=a[rt]; return ; } int m=(l+r)>>1; build(lson,l,m); build(rson,m+1,r); push_up(rt);}void update(int rt,int l,int r,int ql,int qr,int v){ if(ql<=l&&qr>=r) { if(a[rt]!=-1) { a[rt]=(v==-1)?phi[a[rt]]:v; sum[rt]=a[rt]*(r-l+1); return ; } } push_down(rt,l,r); int m=(l+r)>>1; if(ql<=m) update(lson,l,m,ql,qr,v); if(qr>m) update(rson,m+1,r,ql,qr,v); push_up(rt);}ll query(int rt,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r) return sum[rt]; int m=(l+r)>>1; push_down(rt,l,r); ll res=0; if(ql<=m) res+=query(lson,l,m,ql,qr); if(qr>m) res+=query(rson,m+1,r,ql,qr); push_up(rt); return res;}int main(){ int T; init(); scanf("%d",&T); while(T--) { int n,q; scanf("%d%d",&n,&q); build(1,1,n); while(q--) { int op,l,r; scanf("%d%d%d",&op,&l,&r); if(op==1) update(1,1,n,l,r,-1); else if(op==2) { int x; scanf("%d",&x); update(1,1,n,l,r,x); } else printf("%I64d\n",query(1,1,n,l,r)); } } return 0;}
- 线段树题集
- 线段树题集
- 线段树题集
- 线段树题集
- 线段树题集
- 线段树题集
- 线段树题集
- 线段树题集
- 线段
- 线段_线段树
- 线段_线段树
- 线段树?线段树!
- 线段树?线段树!
- 线段与线段 线段与三角形
- 线段树
- 线段树
- 线段树
- 线段树
- 顺序表应用6:有序顺序表查询
- openssh-server
- 多媒体之使用PlaySound播放音频
- 重拾Java--功底篇之HashMap
- 第二章 Linux安装课后习题
- 线段树题集
- 个人总结8
- 纪念重学C/C++,Linux的日子
- Linux网络管理
- 练习 2-5 编写函数 any(s1, s2),将字符串 s2 中的任一字符在字符串 s1 中第一次 出现的位置作为结果返回。如果 s1 中不包含 s2 中的字符,则返回-1
- 实现简单的"nginx+uwsgi+django"的服务器架构
- Java基础面试——final、static注意点
- py3.6中 变量不能同时作为global变量和子函数传递的变量
- 后缀数组题集