SlingShot 求数轴上从x到y的最短路( 边长为1),有若干个从xi到yi长度为ti的传送门,每次只能选择其中一个使用。
即求min(|x-y|,min{|a-x|+|b-y|+c}),拆开绝对值,根据相对位置分开讨论,转换成二维数点问题。
MLE的主席树版本:
1 #include<bits/stdc++.h> 2 #define P pair<ll,ll> 3 #define fir first 4 #define sec second 5 using namespace std; 6 typedef long long ll; 7 int read() 8 { 9 int x=0;char ch=getchar(); 10 while (ch<'0'||ch>'9') ch=getchar(); 11 while ('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 12 return x; 13 } 14 const int N=1e9,T=6e6,M=1e5+5; 15 const ll inf=1ll<<60; 16 P Min[T]; 17 int ls[T],rs[T],A[M],x,y,sc,n,rt0[M],rt1[M],m; 18 struct node{ll a,b,c;}p[M]; 19 bool cmp(const node &A,const node &B) {return A.a<B.a;} 20 P fmin(P a,P b){ 21 return P(min(a.fir,b.fir),min(a.sec,b.sec)); 22 }; 23 void ins(int &k,int pk,int l,int r,int x,P y) 24 { 25 k=++sc;ls[k]=ls[pk];rs[k]=rs[pk];Min[k]=Min[pk]; 26 if (l==r) {Min[k]=fmin(Min[k],y);return;} 27 int mid=(l+r)>>1; 28 if (x<=mid) ins(ls[k],ls[pk],l,mid,x,y); 29 else ins(rs[k],rs[pk],mid+1,r,x,y); 30 Min[k]=fmin(Min[ls[k]],Min[rs[k]]); 31 } 32 P qry(int k,int l,int r,int L,int R) 33 { 34 if (!k) return P(inf,inf); 35 if (L<=l&&r<=R) return Min[k]; 36 int mid=(l+r)>>1;P mn=P(inf,inf); 37 if (L<=mid) mn=fmin(mn,qry(ls[k],l,mid,L,R)); 38 if (R>mid) mn=fmin(mn,qry(rs[k],mid+1,r,L,R)); 39 return mn; 40 } 41 int main() 42 { 43 n=read();m=read();Min[0]=P(inf,inf); 44 for (int i=1;i<=n;i++) 45 p[i].a=read(),p[i].b=read(),p[i].c=read(),A[i]=p[i].a; 46 sort(p+1,p+n+1,cmp); 47 sort(A+1,A+n+1);//寻址数组 48 for (int i=n;i>=1;i--) 49 ins(rt0[i],rt0[i+1],0,N,p[i].b,P(p[i].a-p[i].b+p[i].c,p[i].a+p[i].b+p[i].c)); 50 for (int i=1;i<=n;i++) 51 ins(rt1[i],rt1[i-1],0,N,p[i].b,P(-p[i].a-p[i].b+p[i].c,-p[i].a+p[i].b+p[i].c)); 52 while (m--) 53 { 54 x=read();y=read(); 55 ll ans=abs(x-y); 56 int k=upper_bound(A+1,A+n+1,x)-A-1; 57 ans=min(ans,qry(rt0[k+1],1,N,1,y).fir-x+y); 58 ans=min(ans,qry(rt1[k],1,N,1,y).fir+x+y); 59 ans=min(ans,qry(rt0[k+1],1,N,y,N).sec-x-y); 60 ans=min(ans,qry(rt1[k],1,N,y,N).sec+x-y); 61 printf("%lld\n",ans); 62 } 63 return 0; 64 }
正常二维数点的树状数组版本(AC):
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int read() 5 { 6 int x=0;char ch=getchar(); 7 while (ch<'0'||ch>'9') ch=getchar(); 8 while ('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 9 return x; 10 } 11 const int M=1e5+5; 12 const ll inf=1ll<<60; 13 int A[M],n,m,tot,t,B[M*2]; ll ans[M],bit[M*2]; 14 vector<int> vec1[M],vec2[M]; 15 struct node{ll a,b,c,d;}p[M],q[M]; 16 bool cmp(const node &A,const node &B) {return A.a<B.a;} 17 int lowbit(int x) {return x&(-x);} 18 void add1(int x,ll y){while (x<=tot) bit[x]=min(bit[x],y),x+=lowbit(x);}//前缀最小值 19 ll qry1(int x){ll res=inf;while (x) res=min(res,bit[x]),x-=lowbit(x);return res;} 20 void add2(int x,ll y){while (x) bit[x]=min(bit[x],y),x-=lowbit(x);}//后缀最小值 21 ll qry2(int x){ll res=inf;while (x<=tot) res=min(res,bit[x]),x+=lowbit(x);return res;} 22 void init(){for (int i=1;i<=tot;i++) bit[i]=inf;} 23 int main() 24 { 25 n=read();m=read(); 26 for (int i=1;i<=n;i++) 27 p[i].a=read(),p[i].b=B[++tot]=read(),p[i].c=read(),A[i]=p[i].a; 28 sort(p+1,p+n+1,cmp);sort(A+1,A+n+1);//寻址数组 29 for (int i=1;i<=m;i++) 30 { 31 q[i].a=read(),q[i].b=B[++tot]=read();ans[i]=abs(q[i].a-q[i].b); 32 int k=upper_bound(A+1,A+n+1,q[i].a)-A-1; 33 vec1[k+1].push_back(i); 34 vec2[k].push_back(i); 35 } 36 sort(B+1,B+tot+1);tot=unique(B+1,B+tot+1)-B-1; 37 for (int i=1;i<=n;i++) p[i].d=lower_bound(B+1,B+tot+1,p[i].b)-B; 38 for (int i=1;i<=m;i++) q[i].d=lower_bound(B+1,B+tot+1,q[i].b)-B; 39 init(); 40 for (int i=n;i>=1;i--) 41 { 42 add1(p[i].d,p[i].a-p[i].b+p[i].c); 43 for (int j=0;j<vec1[i].size();j++) 44 t=vec1[i][j],ans[t]=min(ans[t],qry1(q[t].d)-q[t].a+q[t].b); 45 } 46 init(); 47 for (int i=n;i>=1;i--) 48 { 49 add2(p[i].d,p[i].a+p[i].b+p[i].c); 50 for (int j=0;j<vec1[i].size();j++) 51 t=vec1[i][j],ans[t]=min(ans[t],qry2(q[t].d)-q[t].a-q[t].b); 52 } 53 init(); 54 for (int i=1;i<=n;i++) 55 { 56 add1(p[i].d,-p[i].a-p[i].b+p[i].c); 57 for (int j=0;j<vec2[i].size();j++) 58 t=vec2[i][j],ans[t]=min(ans[t],qry1(q[t].d)+q[t].a+q[t].b); 59 } 60 init(); 61 for (int i=1;i<=n;i++) 62 { 63 add2(p[i].d,-p[i].a+p[i].b+p[i].c); 64 for (int j=0;j<vec2[i].size();j++) 65 t=vec2[i][j],ans[t]=min(ans[t],qry2(q[t].d)+q[t].a-q[t].b); 66 } 67 for (int i=1;i<=m;i++) printf("%lld\n",ans[i]); 68 return 0; 69 }
Newbarn 加点x,询问x在树上能走的最远距离
最远距离一定会走到直径端点。维护每棵树的直径(维护一条就够了)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100005; 4 int q,x,dep[N],fa[N][25],id,bel[N],sc,Max,u[N],v[N],tmp; 5 char s[5]; 6 int lca(int x,int y) 7 { 8 if (dep[x]<dep[y]) swap(x,y); 9 int del=dep[x]-dep[y]; 10 for (int i=20;i>=0;i--) 11 if (del&(1<<i)) x=fa[x][i]; 12 if (x==y) return x; 13 for (int i=20;i>=0;i--) 14 if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 15 return fa[x][0]; 16 } 17 int dis(int x,int y) {return dep[x]+dep[y]-2*dep[lca(x,y)];} 18 int main() 19 { 20 scanf("%d",&q); 21 while (q--) 22 { 23 scanf("%s%d",s,&x); 24 if (s[0]=='B') 25 { 26 id++; 27 if (x!=-1) 28 { 29 dep[id]=dep[x]+1,fa[id][0]=x; bel[id]=bel[x]; 30 for (int j=1;j<=20;j++) 31 fa[id][j]=fa[fa[id][j-1]][j-1]; 32 Max=dis(u[bel[id]],v[bel[id]]); 33 if (tmp=dis(id,u[bel[id]]),tmp>Max) Max=tmp,v[bel[id]]=id; 34 if (tmp=dis(id,v[bel[id]]),tmp>Max) Max=tmp,u[bel[id]]=id; 35 }else bel[id]=++sc,u[sc]=v[sc]=id; 36 }else printf("%d\n",max(dis(x,u[bel[x]]),dis(x,v[bel[x]]))); 37 } 38 return 0; 39 }
Cow Gymnasts 求有多少个数组A任意位i都满足A[i]=sigma[A[i-j+1]>=j](i-j+1<=0时从N开始往下)?(1<=A[i]<=N)
关键点在发现循环节。大胆从最小位置x入手,设其值为m,则满足y=x(mod gcd(N,m)的位置y的值都为m。
同样也可以归纳证明,所有位置的值都<=m+1。(注意一个循环节中有一个m+1,那么就不会出现m)
枚举m,$Ans=\sum_{m=1}^{n-1}(2^{\gcd(n,m)}-1)+1$。m=n的情况只有可能全是m,故加1。
把gcd提出来,$Ans=\sum_{d|n}2^d*\varphi(N/d)-N+2-2^N$。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod=1e9+7; 5 #define P pair<ll,int> 6 ll n,ans,sum; 7 map<ll,ll> Phi; 8 vector<P> vec; 9 ll ksm(ll x,ll y) { 10 ll res=1; 11 while (y) {if (y&1) res=res*x%mod; x=x*x%mod;y>>=1;} 12 return res; 13 } 14 void dvd(ll x) 15 { 16 for (int i=2;i<=sqrt(x);i++) 17 if (x%i==0) 18 { 19 sum*=i-1;int cnt=1;x/=i; 20 while (x%i==0) x/=i,cnt++,sum*=i; 21 vec.push_back(P(i,cnt)); 22 } 23 if (x!=1) vec.push_back(P(x,1)); 24 } 25 void dfs(ll x,int d,ll phi) 26 { 27 if (d==vec.size()) {Phi[x]=phi;return;} 28 dfs(x,d+1,phi); 29 ll t=vec[d].first,sum=t-1; 30 for (int i=1;i<=vec[d].second;i++) 31 { 32 x*=t; 33 dfs(x,d+1,phi*sum); 34 sum*=t; 35 } 36 } 37 int main() 38 { 39 scanf("%lld",&n); 40 if (n==1) return puts("1"),0; 41 sum=1;dvd(n); 42 dfs(1,0,1);ans=((2-n-ksm(2,n))%mod+mod)%mod; 43 for (int i=1;i<=sqrt(n);i++) 44 if (n%i==0){ 45 ans+=ksm(2,i)*Phi[n/i]%mod; ans%=mod; 46 if ((ll)i*i!=n) ans+=ksm(2,n/i)*Phi[i]%mod,ans%=mod; 47 } 48 printf("%lld\n",ans); 49 return 0; 50 }