codeforces 803G Periodic RMQ Problem
2018-01-12 17:57
447 查看
codeforces 803G Periodic RMQ Problem
题意
长度为\(1e5\)的数组复制\(1e4\)次,对新的数组进行区间覆盖和区间最小值查询两种操作,操作次数\(1e5\)。参考博客
http://kugwzk.info/index.php/archives/2404题解一
小数组复用多次变成大数组,那么可以用ST表维护小数组的区间最小值,大数组还是用线段树维护\(Min[]\)和\(lazy[]\),但是不用进行build操作,所以upd和qry操作中标记下传的时候儿子节点可能会不存在,需要动态开点。题解二
离线做法。离散化之后用普通线段树就能搞定。总结
写线段树的题目最重要的是,要知道自己在维护什么东西,每个结点上值的意义都要很清楚。代码一
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define rep(i, a, b) for(int i=(a); i<(b); i++) #define sz(x) (int)x.size() #define de(x) cout<< #x<<" = "<<x<<endl #define dd(x) cout<< #x<<" = "<<x<<" " typedef long long ll; typedef pair<int, int> pii; typedef vector<int> vi; //------ const int N=101010; int n,k; int b ; int st [22]; int stmin(int l,int r) { int _=log2(r-l+1); return min(st[l][_], st[r-(1<<_)+1][_]); } int stMin(int l,int r) { int L=l/n, R=r/n; if(L==R) { return stmin(l%n, r%n); } else if(L+1==R) { return min(stmin(l%n, n-1), stmin(0, r%n)); } else { return stmin(0, n-1); } } int cntn; int ls[N*244], rs[N*244], mi[N*244], la[N*244]; void down(int rt, int l, int r, int mid) { bool fl=0, fr=0; if(ls[rt]==-1) ls[rt]=++cntn, fl=1; if(rs[rt]==-1) rs[rt]=++cntn, fr=1; int L=ls[rt], R=rs[rt]; if(la[rt]) { la[L]=mi[L]=la[rt]; la[R]=mi[R]=la[rt]; la[rt]=0; } else { if(fl) mi[L]=stMin(l, mid); if(fr) mi[R]=stMin(mid+1, r); } } void upd(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R) { mi[rt]=la[rt]=c; return ; } int mid=l+r>>1; down(rt, l, r, mid); if(L<=mid) upd(L,R,c,l,mid,ls[rt]); if(R>=mid+1) upd(L,R,c,mid+1,r,rs[rt]); mi[rt]=min(mi[ls[rt]], mi[rs[rt]]); } int qry(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) return mi[rt]; int mid=l+r>>1; down(rt, l, r, mid); int ans=1e9+7; if(L<=mid) ans=min(ans, qry(L, R, l, mid, ls[rt])); if(R>=mid+1) ans=min(ans, qry(L, R, mid+1, r, rs[rt])); return ans; } int main() { while(~scanf("%d%d",&n,&k)) { ///init cntn=0; memset(la,0,sizeof(la)); memset(ls,-1,sizeof(ls)); memset(rs,-1,sizeof(rs)); ///read rep(i,0,n) scanf("%d",b+i); ///st_ini rep(i,0,n) st[i][0]=b[i]; for(int i=1;(1<<i)<=n;++i) { for(int j=0;j+(1<<i)-1<n;++j) { st[j][i]=min(st[j][i-1], st[j+(1<<(i-1))][i-1]); } } ///solve mi[0]=stmin(0, n-1); int q;scanf("%d",&q); while(q--) { int t,l,r;scanf("%d%d%d",&t,&l,&r); --l;--r; if(t==1) { int x;scanf("%d",&x); upd(l, r, x, 0, n*k-1, 0); } else { printf("%d\n",qry(l, r, 0, n*k-1, 0)); } } } return 0; }
代码二
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define rep(i, a, b) for(int i=(a); i<(b); i++) #define sz(x) (int)x.size() #define de(x) cout<< #x<<" = "<<x<<endl #define dd(x) cout<< #x<<" = "<<x<<" " typedef long long ll; typedef pair<int, int> pii; typedef vector<int> vi; //------ const int N=101010; int n,k,q; int st [22]; int stmin(int l,int r) { int _=log2(r-l+1); return min(st[l][_], st[r-(1<<_)+1][_]); } int stMin(int l,int r) { if(l>r) return 1e9+7; int L=l/n, R=r/n; if(L==R) return stmin(l%n, r%n); else if(L+1==R) return min(stmin(l%n, n-1), stmin(0, r%n)); else return stmin(0, n-1); } int cntx; int x[N<<1], val[N<<2]; struct Q { int t,l,r,x; Q() {} Q(int a,int b,int c,int d) { t=a;l=b;r=c;x=d; } }qq ; int mi[N<<4], la[N<<4]; void build(int l, int r, int rt) { la[rt]=0; if(l==r) { mi[rt]=val[l]; return ; } int mid=l+r>>1; build(l, mid, rt<<1); build(mid+1, r, rt<<1|1); mi[rt]=min(mi[rt<<1], mi[rt<<1|1]); } void down(int rt) { if(la[rt]==0) return ; int L=(rt<<1), R=(L|1); la[L]=mi[L]=la[R]=mi[R]=la[rt]; la[rt]=0; } void upd(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R) { mi[rt]=la[rt]=c; return ; } int mid=l+r>>1; down(rt); if(L<=mid) upd(L,R,c,l,mid,rt<<1); if(R>=mid+1) upd(L,R,c,mid+1,r,rt<<1|1); mi[rt]=min(mi[rt<<1], mi[rt<<1|1]); } int qry(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) return mi[rt]; down(rt); int mid=l+r>>1; int ans=1e9+7; if(L<=mid) ans=min(ans,qry(L,R,l,mid,rt<<1)); if(R>=mid+1) ans=min(ans,qry(L,R,mid+1,r,rt<<1|1)); return ans; } int main() { while(~scanf("%d%d",&n,&k)) { ///init cntx=0; ///read rep(i,0,n) scanf("%d",&st[i][0]); scanf("%d",&q); rep(i,0,q) { int t,l,r,xx=0;scanf("%d%d%d",&t,&l,&r); --l;--r; if(t==1) scanf("%d",&xx); qq[i]=Q(t,l,r,xx); x[++cntx]=l; x[++cntx]=r; } ///st for(int i=1;(1<<i)<=n;++i) { for(int j=0;j+(1<<i)-1<n;++j) { st[j][i]=min(st[j][i-1], st[j+(1<<(i-1))][i-1]); } } ///solve sort(x+1,x+1+cntx); cntx=unique(x+1, x+1+cntx)-x-1; rep(i,1,cntx+1) val[i<<1]=st[x[i]%n][0]; rep(i,1,cntx) val[i<<1|1]=stMin(x[i]+1, x[i+1]-1); build(2, cntx<<1, 1); rep(i,0,q) { int t=qq[i].t; int l=qq[i].l; int r=qq[i].r; int c=qq[i].x; int L=lower_bound(x+1, x+1+cntx, l)-x; int R=lower_bound(x+1, x+1+cntx, r)-x; if(t==1) { upd(L<<1, R<<1, c, 2, cntx<<1, 1); } else { printf("%d\n",qry(L<<1, R<<1, 2, cntx<<1, 1)); } } } return 0; }
相关文章推荐
- codeforces 803G Periodic RMQ Problem
- Codeforces 803 G. Periodic RMQ Problem
- AC日记——Periodic RMQ Problem codeforces 803G
- Educational Codeforces Round 20 G. Periodic RMQ Problem(线段树动态开点)
- (WAWAWAWAWAWAW) G. Periodic RMQ Problem
- Educational Codeforces Round 20 G. Periodic RMQ Problem(线段树+主席树)
- codeforces contest 13 problem E(分块)
- Codeforces 689D Friends and Subsequences(二分+RMQ)
- CodeForces - 1000D:Yet Another Problem On a Subsequence (DP+组合数)
- Codeforces 472D. Design Tutorial: Inverse the Problem(一种逆向判定树成立的办法,从Kruskal到dfs)
- Codeforces 798C:Mike and gcd problem
- Soldier and Cards(Problem - 546C - Codeforces)
- codeforces 459D - Pashmak and Parmida's problem【离散化+处理+逆序对】
- bzoj 3489 A simple rmq problem - 线段树
- problem - 616B -codeforces
- BZOJ 3489 A simple rmq problem 可持久化树套树
- CodeForces 689D Friends and Subsequences (RMQ+二分)
- Codeforces 742 B. Arpa’s obvious problem and Mehrdad’s terrible solution
- Problem--116A--Codeforces--Tram
- Luogu4137:Rmq Problem/mex