「PKUSC2018」星际穿越
咕了很久的一道题
令(L_i=minlimits_{j=i}^nl_j)
发现从x开始走一步可以到达的最小的点为(l_x) 最大的是满足(l_j le x)最靠右的(j)
而第二次能到达的最靠左的点(L_{l_x}) 因为第一步到不了的右边的点的(l)一定不产生贡献
记第(a)次能到达的最靠左的点为(b) 第(a+1)次可以到达的最靠左的点为(L_b)
第二步及以后可以当作每次跳(L_i) 构成了树形结构 可以用主席树或者倍增之类的东西维护(对我来说倍增不好想不好写 太弱了)
第一步只会有两种走法
如果(yin[l_x,x-1]) 可以一步走到
否则 跳到(jin[l_x,n]) 中(l_j)最小的j 然后到达(L_{l_x})
特殊判一下即可
做了好长一段时间……
#include<bits/stdc++.h>
using namespace std;
#define fp(i,l,r) for(register int (i)=(l);(i)<=(r);++(i))
#define fd(i,l,r) for(register int (i)=(l);(i)>=(r);--(i))
#define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next)
#define mem(a) memset((a),0,sizeof (a))
#define O(x) cerr<<#x<<':'<<x<<endl
#define int long long
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
void wr(int x){
if(x<0)x=-x,putchar('-');
if(x>=10)wr(x/10);
putchar('0'+x%10);
}
const int MAXN=3e5+10;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int l[MAXN],L[MAXN],sum[MAXN*30],n;
signed ls[MAXN*30],rs[MAXN*30],tag[MAXN*30],cnt,rt[MAXN];
void mdy(signed &o,signed pre,int l,int r,int ql,int qr){
o=++cnt;tag[o]=tag[pre];sum[o]=sum[pre]+(qr-ql+1);ls[o]=ls[pre];rs[o]=rs[pre];
if(l==ql&&r==qr){++tag[o];return;}
int mid=l+r>>1;
if(qr<=mid)mdy(ls[o],ls[pre],l,mid,ql,qr);
else if(ql>mid)mdy(rs[o],rs[pre],mid+1,r,ql,qr);
else mdy(ls[o],ls[pre],l,mid,ql,mid),mdy(rs[o],rs[pre],mid+1,r,mid+1,qr);
}
int ask(signed o,int l,int r,int ql,int qr){
if(!o)return 0;
if(l==ql&&r==qr)return sum[o];
int mid=l+r>>1,res=(qr-ql+1)*tag[o];
if(qr<=mid)return res+ask(ls[o],l,mid,ql,qr);
else if(ql>mid)return res+ask(rs[o],mid+1,r,ql,qr);
else return res+ask(ls[o],l,mid,ql,mid)+ask(rs[o],mid+1,r,mid+1,qr);
}
main(){
n=read();
fp(i,2,n)l[i]=read();
L[n]=l[n];fd(i,n-1,2)L[i]=min(L[i+1],l[i]);
fp(i,2,n)mdy(rt[i],rt[L[i]],1,n,1,i-1);
int Q=read();
while(Q--){
int ql=read(),qr=read(),x=read();int t=min(qr,l[x]-1);
int t1=qr-ql+1,t2=t1+(ql<=t?ask(rt[l[x]],1,n,ql,t):0);
int g=gcd(t1,t2);
printf("%lld/%lld
",t2/g,t1/g);
}
return 0;
}
「SCOI2015」国旗计划
破环为链
设(dp_{i,j})表示从(i)开始走(2^j)步
每次找的时候从其实位置走上m