[NOI.AC]NOI2019省选模拟赛 第二场

传送门

Solution

A.

一共有\(T\)组数据

每次询问你\([l,r]\)中有多少个数能被他的所有数位整除(如果数位中含有\(0\)忽略掉)

数位dp,咕咕咕

B.

题面略

考虑一个个只有两个元素组成的小区间
可以发现若选择\([l,l+1]\),则必定要选择一个最大的区间包含\([a[l],a[l+1]]\)的区间
每个小区间看成一个点,向它所要求必须要选择的点连边,线段树优化建图
对图进行tarjan缩点,然后拓扑排序即可
全是区间询问,大概要有5棵线段树的样子

C.

题面略

经过一波推导可得:\(a_i=x_{i+1}x_i-c_1(c_2-c_1)\)
所以分块+矩阵快速幂就完事了
没开ll会re,虽然到最后也不知道到底是哪里没开ll


Code 

/*
    B 2019/3/18 
*/
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const int MN=1e5+5;
int N,Q,a[MN],b[MN],ls[MN*3],rs[MN*3],tt,root,minb[MN<<2],maxb[MN<<2];
struct edge{int to,nex;}e[MN<<4];int en,hr[MN*3];
inline void ins(int f,int t){e[++en]=(edge){t,hr[f]};hr[f]=en;} 
inline void build(int &x,int l,int r)
{
    if(l==r){x=l;return;}register int mid=(l+r)>>1;
    x=++tt;build(ls[x],l,mid);build(rs[x],mid+1,r);
    ins(x,ls[x]);ins(x,rs[x]);
}
inline void Build(int x,int l,int r)
{
    if(l==r){minb[x]=maxb[x]=b[l];return;}int mid=(l+r)>>1;
    Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
    minb[x]=min(minb[x<<1],minb[x<<1|1]);
    maxb[x]=max(maxb[x<<1],maxb[x<<1|1]);
}
inline int qmi(int x,int l,int r,int a,int b)
{
    if(a==l&&b==r)return minb[x];int mid=(l+r)>>1;
    if(b<=mid) return qmi(x<<1,l,mid,a,b);
    else if(a>mid) return qmi(x<<1|1,mid+1,r,a,b);
    return min(qmi(x<<1,l,mid,a,mid),qmi(x<<1|1,mid+1,r,mid+1,b)); 
}
inline int qma(int x,int l,int r,int a,int b)
{
    if(a==l&&b==r)return maxb[x];int mid=(l+r)>>1;
    if(b<=mid) return qma(x<<1,l,mid,a,b);
    else if(a>mid) return qma(x<<1|1,mid+1,r,a,b);
    return max(qma(x<<1,l,mid,a,mid),qma(x<<1|1,mid+1,r,mid+1,b));
}
inline void Insert(int x,int l,int r,int a,int b,int t)
{
    if(l==a&&r==b){ins(t,x);return;}
    int mid=(l+r)>>1;
    if(b<=mid) Insert(ls[x],l,mid,a,b,t);
    else if(a>mid) Insert(rs[x],mid+1,r,a,b,t);
    else Insert(ls[x],l,mid,a,mid,t),Insert(rs[x],mid+1,r,mid+1,b,t); 
}
int bel[MN*3],Mi[MN*3],Ma[MN*3],dfn[MN*3],low[MN*3],dind,st[MN*3],tp,bl;
int getv(int x){if(x>N)return 0;return x;}bool in[MN*3];
inline void rwi(int &x,int y){if(y<x)x=y;}
inline void rwa(int &x,int y){if(y>x)x=y;}
void tj(int x)
{
    dfn[x]=low[x]=++dind;st[tp++]=x;in[x]=true;
    register int i;
    for(i=hr[x];i;i=e[i].nex) 
    {
        if(!dfn[e[i].to]) tj(e[i].to),low[x]=min(low[x],low[e[i].to]);
        else if(in[e[i].to])low[x]=min(low[x],low[e[i].to]);
    }
    if(low[x]==dfn[x])
    {
        ++bl;
        for(;st[tp]!=x;in[st[--tp]]=false)bel[st[tp-1]]=bl,rwi(Mi[bl],st[tp-1]),rwa(Ma[bl],getv(st[tp-1]));
    }
}
inline void Built(int x,int l,int r)
{
    if(l==r){minb[x]=Mi[bel[l]];maxb[x]=Ma[bel[l]];return;}
    register int mid=(l+r)>>1;
    Built(x<<1,l,mid);Built(x<<1|1,mid+1,r);
    minb[x]=min(minb[x<<1],minb[x<<1|1]);
    maxb[x]=max(maxb[x<<1],maxb[x<<1|1]);
}
edge E[MN<<4];int En=0,Hr[MN*3],rd[MN*3];
inline void Ins(int f,int t){++rd[t];E[++En]=(edge){t,Hr[f]};Hr[f]=En;}
std::queue<int> q;
void jt()
{
    register int i,j,I,J;
    memset(Hr,0,sizeof Hr);
    for(i=1;i<=tt;++i) for(j=hr[i];j;j=e[j].nex)
        if(bel[i]^bel[e[j].to]) Ins(bel[e[j].to],bel[i]);
    for(i=1;i<=bl;++i) if(!rd[i]) q.push(i);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(i=Hr[u];i;i=E[i].nex)
        {
            if(Ma[u]) rwa(Ma[E[i].to],Ma[u]);
            if(Mi[u]<N) rwi(Mi[E[i].to],Mi[u]);
            if(!--rd[E[i].to]) q.push(E[i].to);
        }
    }
}
int main()
{
    register int i,j;
    tt=N=read();for(i=1;i<=N;++i)b[a[i]=read()]=i;
    build(root,1,N-1);Build(1,1,N);
    for(i=1;i<N;++i)
    {
        int l=a[i],r=a[i+1],mi,ma;
        if(l>r) std::swap(l,r);
        mi=qmi(1,1,N,l,r);ma=qma(1,1,N,l,r);--ma;
        if(mi<i) Insert(root,1,N-1,mi,i-1,i);
        if(ma>i) Insert(root,1,N-1,i+1,ma,i);
    }
    memset(Mi,0x3f,sizeof Mi);
    for(i=1;i<=tt;++i) if(i!=N&&!dfn[i]) tj(i);jt();
    memset(minb,0,sizeof minb);memset(maxb,0,sizeof maxb);
    Built(1,1,N-1);Q=read();
    while(Q--)
    {
        int l=read(),r=read(),mi,ma;--r;
        if(l>r){printf("%d %d\n",l,l);continue;}
        mi=qmi(1,1,N-1,l,r);ma=qma(1,1,N-1,l,r);
        printf("%d %d\n",mi,ma+1);
    }
    return 0;
}


/*
    C 2019/3/18
*/ 
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define reg register
ll N,M,P,Q,_1,_2;
std::map<ll,ll> mp;
const ll MN=2e5+5;
struct matrix
{
    ll a[3][3];
    matrix(){memset(a,0,sizeof a);}
    matrix operator *(const matrix o)
    {
        reg int i,j,k;matrix c;
        for(k=0;k<2;++k)for(i=0;i<2;++i)for(j=0;j<2;++j)
            (c.a[i][j]+=(1ll*o.a[i][k]*a[k][j])%P)%=P;
        return c;
    }
}L[MN],R[MN],ep,_;
ll ans[MN<<1],dec;
ll Cal(ll num)
{
    ll x=(num-1)/M,y=(num-1)%M+1;
    matrix t;
    t=L[x]*R[y];
    ll xi=(1ll*t.a[0][0]*_1%P+1ll*t.a[0][1]*_2%P)%P;
    ll xi_=(1ll*t.a[1][0]*_1%P+1ll*t.a[1][1]*_2%P)%P;
    return (1ll*xi_*xi%P+dec)%P;
}
ll cal(ll x,ll y)
{
    if(mp.count(1ll*(x-1)*M+y)) return (Cal(mp[1ll*(x-1)*M+y])+P)%P;
    else return (Cal(1ll*(x-1)*M+y)+P)%P;
}
signed main()
{
    ll x,y,i,j;
    N=read(),M=read();Q=read();P=read();_1=read();_2=read();
    dec=1ll*_1*((_2-_1+P)%P)%P;dec=1ll*(P-dec)%P;
    while(Q--)
    {
        x=read();y=read();
        i=mp.count(x)?mp[x]:x;j=mp.count(y)?mp[y]:y;
        mp[x]=j;mp[y]=i;
    }
    ep.a[0][0]=ep.a[1][1]=1;ep.a[0][1]=ep.a[1][0]=0;
    _.a[0][1]=_.a[1][0]=_.a[1][1]=1;_.a[0][0]=0;
    R[0]=ep;for(i=1;i<=M;++i)R[i]=R[i-1]*_;
    L[0]=ep;for(i=1;i<=N;++i)L[i]=L[i-1]*R[M];
    ans[1]=cal(1,1);
    for(i=1,j=1;i<=N&&j<=M;)
    {
        if(i<N)x=cal(i+1,j);else x=P+1;
        if(j<M)y=cal(i,j+1);else y=P+1;
        ans[i+j]=min(x,y);
        if(x<=y) i++;else j++;
        if(i==N&&j==M)break;
    }
    for(i=1;i<N+M;++i) printf("%lld ",ans[i]);
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

猜你喜欢

转载自www.cnblogs.com/PaperCloud/p/noiacnoi2019_2.html
今日推荐