【HHHOJ】ZJOI2019模拟赛(十六)4.07 解题报告

点此进入比赛

得分: \(100+100+100=300\)

排名: \(Rank\ 1\)

\(Rating\): \(+13\)(\(\frac18Rated\))

备注: 这场比赛全是做过的原题。。。因此下面只放代码,题解可见每道题相应链接。

\(T1\):【HHHOJ203】A(点此看题面

题解详见:【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)

代码如下:

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define swap(x,y) (x^=y^=x^=y)
#define pb(x,y) (nxt[y]=lnk[x],lnk[x]=y) 
using namespace std;
int n,m,a[N+5],q[N+5],lnk[N+5],nxt[N+5],ans[N+5];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
    public:
        I FastIO() {A=B=FI;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
        Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
        I void readbit(int& x) {W(!D);x=c&1;}
        I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
template<int SZ> class SuffixAutomation//后缀自动机
{
    private:
        int lst;struct Trie {int L,F,S[2];}O[SZ<<1];
    public:
        int tot,l[SZ<<1],f[SZ<<1];I SuffixAutomation() {tot=lst=1;}
        I void Record() {for(RI i=1;i<=tot;++i) l[i]=O[i].L,f[i]=O[i].F;}
        I int Insert(CI x)//插入节点
        {
            RI p=lst,q,k,now=lst=++tot;O[now].L=O[p].L+1;
            W(p&&!O[p].S[x]) O[p].S[x]=now,p=O[p].F;if(!p) return O[now].F=1,now;
            if(O[p].L+1==O[q=O[p].S[x]].L) return O[now].F=q,now;
            O[k=++tot]=O[q],O[k].L=O[p].L+1,O[now].F=O[q].F=k;
            W(p&&!(O[p].S[x]^q)) O[p].S[x]=k,p=O[p].F;return now;
        }
};
template<int SZ> class TreeArray//树状数组
{
    private:
        #define lowbit(x) ((x)&-(x))
        int a[SZ+5];
    public:
        I void Add(RI x,CI v) {W(x) Gmax(a[x],v),x-=lowbit(x);}//单点修改
        I int Qry(RI x) {RI t=0;W(x<=n) Gmax(t,a[x]),x+=lowbit(x);return t;}//区间询问
};
class LinkCutTree//LCT
{
    private:
        #define Upt(x,v) (O[x].f=O[x].V=v)
        #define PD(x) (O[x].f&&(Upt(O[x].S[0],O[x].f),Upt(O[x].S[1],O[x].f),O[x].f=0))
        #define IR(x) (O[O[x].F].S[0]^x&&O[O[x].F].S[1]^x)
        #define Wh(x) (O[O[x].F].S[1]==x)
        #define Co(x,y,d) (O[O[x].F=y].S[d]=x)
        static Con int SZ=N<<1;int p[SZ+5],St[SZ+5];struct node {int f,V,F,S[2];}O[SZ+5];
        SuffixAutomation<N> SAM;TreeArray<N<<1> T;
        I void Ro(CI x)
        {
            RI f=O[x].F,p=O[f].F,d=Wh(x);!IR(f)&&(O[p].S[Wh(f)]=x);
            O[x].F=p,Co(O[x].S[d^1],f,d),Co(f,x,d^1);
        }
        I void S(CI x)
        {
            RI f=x,T=0;W(St[++T]=f,!IR(f)) f=O[f].F;W(T) PD(St[T]),--T;
            W(!IR(x)) f=O[x].F,!IR(f)&&(Ro(Wh(x)^Wh(f)?x:f),0),Ro(x);
        }
    public:
        I void Init(CI x,int* v) 
        {
            RI i;for(i=1;i<=n;++i) p[i]=SAM.Insert(v[i]);SAM.Record();
            for(i=1;i<=SAM.tot;++i) O[i].F=SAM.f[i];
        }
        I void Ac(RI x,CI v)//Access求LCA的过程,注意更新节点信息与答案
        {
            RI s;for(x=p[x],s=0;x;x=O[s=x].F) S(x),
                T.Add(O[x].V,SAM.l[x]),O[x].S[1]=s;Upt(s,v);
        }
        I int Query(CI x) {return T.Qry(x);}//询问答案
}LCT;
int main()
{
    RI Qtot,i,j,x;for(F.read(n,Qtot),i=1;i<=n;++i) F.readbit(a[i]);
    for(LCT.Init(n,a),i=1;i<=Qtot;++i) F.read(q[i],x),pb(x,i);//离线用邻接表存储
    for(i=1;i<=n;++i) for(LCT.Ac(i,i),j=lnk[i];j;j=nxt[j]) ans[j]=LCT.Query(q[j]);//枚举右端点,更新信息并处理询问
    for(i=1;i<=Qtot;++i) F.writeln(ans[i]);return F.clear(),0;//输出答案
}

\(T2\):【HHHOJ204】B(点此看题面

题解详见:【LOJ6042】「雅礼集训 2017 Day7」跳蚤王国的宰相(思博题)

代码如下:

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define INF 1e9
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,p,rt,cnt,ee,s[N+5],lnk[N+5],Sz[N+5],Mx[N+5],ans[N+5];struct edge {int to,nxt;}e[N<<1];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
    public:
        I FastIO() {A=B=FI;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
        Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
        I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
I void GetRt(CI x,CI lst=0)//求重心
{
    for(RI i=(Sz[x]=1,Mx[x]=0,lnk[x]);i;i=e[i].nxt) e[i].to^lst&&
        (GetRt(e[i].to,x),Sz[x]+=Sz[e[i].to],Gmax(Mx[x],Sz[e[i].to]));
    Gmax(Mx[x],n-Sz[x]),Mx[x]<Mx[rt]&&(rt=x);
}
I void Init(CI x,CI lst=0)//初始化Size
{
    for(RI i=(Sz[x]=1,lnk[x]);i;i=e[i].nxt) 
        e[i].to^lst&&(Init(e[i].to,x),Sz[x]+=Sz[e[i].to]);
}
I void GetAns(CI x,CI lst,CI v)//求解答案
{
    ans[x]=p,(Sz[x]+v<<1)>=n&&--ans[x];//判断答案是否可以减1
    for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(GetAns(e[i].to,x,v),0);//遍历子树
}
I bool cmp(CI x,CI y) {return Sz[x]>Sz[y];}//按Size排序
int main()
{
    RI i,x,y;for(F.read(n),i=1;i^n;++i) F.read(x,y),add(x,y),add(y,x);//读入+建边
    for(Mx[rt=0]=INF,GetRt(1),Init(rt),cnt=0,i=lnk[rt];i;i=e[i].nxt) s[++cnt]=e[i].to;//找到重心,将重心儿子存下来用于排序
    for(sort(s+1,s+cnt+1,cmp),x=0,i=1;i<=cnt&&(x<<1)<n;++i) x+=Sz[s[i]];p=i-1;//排序,然后求出p
    for(i=1;i<=cnt;++i) GetAns(s[i],rt,x-max(Sz[s[i]],Sz[s[p]]));//枚举子节点处理答案
    for(i=1;i<=n;++i) F.writeln(ans[i]);return F.clear(),0;//输出
}

\(T3\):【HHHOJ205】C(点此看题面

题解详见:【LOJ6043】「雅礼集训 2017 Day7」蛐蛐国的修墙方案(搜索技巧题)

代码如下:

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100
using namespace std;
int n,tot,a[N+5],v[N+5];char s[N+5];vector<int> f[N+5];
I void Check()//验证是否为合法括号序列
{
    for(RI i=1,t=0;i<=n;++i) if((t+=(s[i]^')'?1:-1))<0) return;//若出现不合法,直接退出函数
    puts(s+1),exit(0);//合法则输出答案,退出程序
}
I void dfs(CI x)//搜索,判断第i个环的填法
{
    if(x>tot) return Check();RI i,sz=f[x].size();
    if(!(sz^2)) return s[f[x][0]]='(',s[f[x][1]]=')',dfs(x+1);//特判环长为2的情况
    for(i=0;i^sz;++i) s[f[x][i]]=(i&1?'(':')');dfs(x+1);//环中必然是左右括号交替
    for(i=0;i^sz;++i) s[f[x][i]]=(i&1?')':'(');dfs(x+1);//枚举另一种情况
}
int main()
{
    RI i,x;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i);//读入
    for(i=1;i<=n;++i) if(!v[x=i])//如果没访问过
        {++tot;W(!v[x]) v[x]=1,f[tot].push_back(x),x=a[x];}//找环
    return dfs(1),0;//搜索
}
上一篇:[ZJOI2019]语言


下一篇:Luogu P5280 [ZJOI2019]线段树