Codeforces 803 G. Periodic RMQ Problem

题目链接:http://codeforces.com/problemset/problem/803/G


 

大致就是线段树动态开节点。

然后考虑到如果一个点还没有出现过,那么这个点显然未被修改,就将这个点所代表的区间定位到原序列中,利用ST表查一下区间最小值就可以了。

定位:

1 llg minn(llg l,llg r)
2 {
3     if(r-l+1>=n) return mt;
4     l%=n;if(!l) l=n;
5     r%=n;if(!r) r=n;
6     if(l>r) return min(gw(l,n),gw(1,r));
7     else return gw(l,r);
8 }

其中${gw(l,r)}$表示原序列${[l,r]}$中元素的最小值。

 

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<cstring>
  7 #include<queue>
  8 #include<vector>
  9 #include<map>
 10 using namespace std;
 11 #define llg int
 12 #define inf 0x7fffffff
 13 #define maxn 500010
 14 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 15 llg ST[maxn][20],mt=inf,n,k,Q,pre[maxn],cnt;
 16 
 17 struct point
 18 {
 19     llg lc,rc,l,r,set,val;
 20 }po[maxn*30];
 21 
 22 inline llg getint()
 23 {
 24     llg w=0,q=0; char c=getchar();
 25     while((c<'0' || c>'9') && c!='-') c=getchar();
 26     if (c=='-')  q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
 27     return q ? -w : w;
 28 }
 29 
 30 llg gw(llg l,llg r)
 31 {
 32     int k=pre[r-l+1];
 33     return min(ST[l][k],ST[r-(1<<k)+1][k]);
 34 }
 35 
 36 llg minn(llg l,llg r)
 37 {
 38     if(r-l+1>=n) return mt;
 39     l%=n;if(!l) l=n;
 40     r%=n;if(!r) r=n;
 41     if(l>r) return min(gw(l,n),gw(1,r));
 42     else return gw(l,r);
 43 }
 44 
 45 void make_st()
 46 {
 47     for(llg i=2;i<=n;i++) pre[i]=pre[i>>1]+1;
 48     for(llg i=1;i<=n;i++) ST[i][0]=getint();
 49     for(llg i=1;i<=n;i++) mt=min(mt,ST[i][0]);
 50     for(llg i=2;i<=n;i++) pre[i]=pre[i>>1]+1;
 51     for(llg j=1;j<=17;j++)
 52         for(llg i=1,u=(1<<j),p=(u>>1);i+u-1<=n;i++)
 53             ST[i][j]=min(ST[i][j-1],ST[i+p][j-1]);
 54     cnt=1,po[1].l=1,po[1].r=n*k,po[1].val=mt;
 55 }
 56 
 57 llg new_po(llg l,llg r)
 58 {
 59     llg o=++cnt;
 60     po[o].val=minn(l,r);
 61     po[o].l=l,po[o].r=r;
 62     return o;
 63 }
 64 
 65 void update(llg o)
 66 {
 67     if (po[o].l==po[o].r) return ;
 68     po[o].val=inf;
 69     if (po[o].lc) po[o].val=min(po[o].val,po[po[o].lc].val);
 70     else
 71     {
 72         po[o].lc=cnt+1;
 73         new_po(po[o].l,(po[o].l+po[o].r)/2);
 74         po[o].val=min(po[o].val,po[po[o].lc].val);        
 75     }
 76     if (po[o].rc) po[o].val=min(po[o].val,po[po[o].rc].val);
 77     else
 78     {
 79         po[o].rc=cnt+1;
 80         new_po((po[o].l+po[o].r)/2+1,po[o].r);
 81         po[o].val=min(po[o].val,po[po[o].rc].val);
 82     }
 83 }
 84 
 85 void pushdown(llg o)
 86 {
 87     llg l=po[o].l,r=po[o].r,lc=po[o].lc,rc=po[o].rc,mid=(l+r)>>1;
 88     if (!po[o].set || l==r) return ;
 89     if (!lc)
 90     {
 91         lc=cnt+1;
 92         new_po(l,mid);
 93     }
 94     if (!rc) 
 95     {
 96         rc=cnt+1;
 97         new_po(mid+1,r);
 98     }
 99     po[lc].set=po[rc].set=po[lc].val=po[rc].val=po[o].set;
100     po[o].set=0;
101     po[o].lc=lc;
102     po[o].rc=rc;
103     return ;
104 }
105 
106 void modify(llg o,llg l,llg r,llg L,llg R,llg v)
107 {
108     pushdown(o);
109     if (o==0) o=new_po(l,r);    
110     llg mid=(l+r)>>1;
111     if (l>=L && r<=R)
112     {
113         po[o].val=v;
114         po[o].set=v;
115         return ;
116     }
117     if (mid>=L) 
118     {
119         llg son=po[o].lc;
120         if (po[o].lc==0) po[o].lc=cnt+1;
121         modify(son,l,mid,L,R,v);
122     }
123     if (mid<R)
124     {
125         llg son=po[o].rc;
126         if (po[o].rc==0) po[o].rc=cnt+1;
127         modify(son,mid+1,r,L,R,v);
128     }
129     update(o);
130 }
131 
132 llg query(llg o,llg l,llg r,llg L,llg R)
133 {
134     pushdown(o);
135     if (o==0) o=new_po(l,r);
136     if (l>=L && r<=R) return po[o].val;
137     llg mid=(l+r)>>1,ans=inf;
138     if (mid>=L)
139     {
140         llg son=po[o].lc;
141         if (po[o].lc==0) po[o].lc=cnt+1;
142         ans=min(ans,query(son,l,mid,L,R));
143     }
144     if (mid<R)
145     {
146         llg son=po[o].rc;
147         if (po[o].rc==0) po[o].rc=cnt+1;
148         ans=min(ans,query(son,mid+1,r,L,R));
149     }
150     return ans;
151 }
152 
153 int main()
154 {
155     yyj("seg");
156     cin>>n>>k;
157     make_st();
158     llg T=n*k;
159     cin>>Q;
160     while (Q--)
161     {
162         llg ty=getint(),l=getint(),r=getint();
163         if (ty==1) 
164             modify(1,1,T,l,r,getint());
165         else 
166             printf("%d\n",query(1,1,T,l,r));
167     }
168     return 0;
169 }

 

转载于:https://www.cnblogs.com/Dragon-Light/p/6794691.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值