标签:phi JZOJ7521 int LL tot 嘉然 ask top
【JZOJ7521】嘉然
by AmanoKumiko
Description
嘉然今天吃欧拉函数
给出一个长为\(n\)排列\(p\)
\(q\)组询问,每次给出一个\(l,r\),求\(\max_{l\le i<j\le r}φ(p_ip_j)\)
Input
第一行一个整数\(n\)
然后一行\(n\)个整数读入\(p\)
第三个一个整数\(q\)
然后\(q\)行读入询问
Output
每组询问一行一个整数表示答案
Sample Input
6
3 2 5 4 1 6
8
4 5
2 6
3 5
2 3
3 4
1 5
4 5
2 6
Sample Output
2
8
8
4
8
8
2
8
Data Constraint
\(1\le n,q\le 5*10^5\)
Solution
我好想做嘉然小姐的狗啊~
考虑分解\(φ(ij)=\frac{φ(i)φ(j)(i,j)}{φ((i,j))}\)
我们枚举\((i,j)\),,然后把对答案的贡献写成三元组\((i,j,φ(ij))\)
最后按将询问按右端点排序解决
但是三元组个数太多,观察一下性质
对于\(j<k<i\)
若有\(φ(k)\ge φ(i),φ(j)\geφ(i)\)
那么\([j,k]\)被\([j,i]\)包含而且贡献更大,那么\(j,i\)的三元组肯定没用
所以只要用单调栈找到左右第一个\(φ\)值更大的就行了
Code
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 500010
#define M 13000010
#define LL long long
#define ls x<<1
#define rs (x<<1)|1
namespace IO{
const int sz=1<<22;
char a[sz+5],b[sz+5],*p1=a,*p2=a,*t=b,p[105];
inline char gc(){
return p1==p2?(p2=(p1=a)+fread(a,1,sz,stdin),p1==p2?EOF:*p1++):*p1++;
}
template<class T>void read(T&x){
x=0;char c=gc();
for(;c<'0'||c>'9';c=gc());
for(;c>='0'&&c<='9';c=gc())x=x*10+(c-'0');
}
inline void flush(){fwrite(b,1,t-b,stdout),t=b;}
inline void pc(char x){*t++=x;if(t-b==sz)flush();}
template<class T>void write(T x,char c='\n'){
if(x==0)pc('0');int t=0;
for(;x;x/=10)p[++t]=x%10+'0';
for(;t;--t)pc(p[t]);pc(c);
}
struct F{~F(){flush();}}f;
}
using IO::read;
using IO::write;
LL v[M],ans[N];
int n,m,p[N],cnt,last[N],phi[N],tot,prime[N],vis[N],q[N],top,d[N],ds,pos[N];
struct edge{
int en[M],nxt[M],last[N],tot;
inline void line(int x,int y,LL z){en[++tot]=y;nxt[tot]=last[x];v[tot]=z;last[x]=tot;}
}e;
struct node{int l,r,pos;}ask[N];
struct tree{
LL Max[N*4];
int lowbit(int x){return -x&x;}
inline void change(int x,LL y){for(;x;x-=lowbit(x))Max[x]=max(Max[x],y);}
inline LL query(int x){LL res=0;for(;x<=n;x+=lowbit(x))res=max(res,Max[x]);return res;}
}t;
inline bool cmp(node x,node y){return x.r<y.r;}
int main(){
freopen("diana.in","r",stdin);
freopen("diana.out","w",stdout);
vis[1]=phi[1]=1;
fo(i,2,N-10){
if(!vis[i])prime[++tot]=i,phi[i]=i-1;
for(int j=1;1ll*i*prime[j]<=N-10&&j<=tot;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])){phi[i*prime[j]]=phi[i]*prime[j];break;}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
read(n);
fo(i,1,n)read(p[i]),pos[p[i]]=i;
fo(i,1,n){
top=0;
ds=0;
for(int j=i;j<=n;j+=i)d[++ds]=pos[j];
sort(d+1,d+ds+1);
fo(j,1,ds){
int x=d[j];
while(phi[p[x]]>phi[p[q[top]]]&&top)top--;
if(top)e.line(x,q[top],1ll*phi[p[q[top]]]*phi[p[x]]*i/phi[i]);
q[++top]=x;
}
top=0;
fd(j,ds,1){
int x=d[j];
while(phi[p[x]]>phi[p[q[top]]]&&top)top--;
if(top)e.line(q[top],x,1ll*phi[p[q[top]]]*phi[p[x]]*i/phi[i]);
q[++top]=x;
}
}
read(m);
fo(i,1,m)read(ask[i].l),read(ask[i].r),ask[i].pos=i;
sort(ask+1,ask+m+1,cmp);
int h=0;
fo(i,1,m){
while(h+1<=ask[i].r&&h+1<=n){
h++;for(int j=e.last[h];j;j=e.nxt[j])t.change(e.en[j],v[j]);
}
ans[ask[i].pos]=t.query(ask[i].l);
}
fo(i,1,m)write(ans[i]);
return 0;
}
标签:phi,JZOJ7521,int,LL,tot,嘉然,ask,top 来源: https://www.cnblogs.com/AmanoKumiko/p/16070059.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。