SDOI2013 R1 Day1

Posted SovietPower

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDOI2013 R1 Day1相关的知识,希望对你有一定的参考价值。

2018.3.22 Test

时间:7:30~11:40
得分:80+65+20=165

T1

题目链接

T2

题目链接

T3 BZOJ.3124.[SDOI2013]直径(树 直径)

题目链接

需要判断一条边是否是所有直径都经过的边
可以证明(想象),树上的多条直径一定是从某个(些)点出发,中间经过同一条链(为方便把链上的边叫做关键边好了),再于某个(些)点结束。
只需要判断当前求出直径上的所有边是否为关键边。如果一条边(u->v)不是关键边,那么说明它(直径上)的前驱u,除了v之外还有u->v‘可以满足最长(得到直径),于是对每个点记录子节点的最远(直径)、次远距离(非严格,在另一棵子树上)就好了。
如果是从R1出发,这样我们可以判掉R2那边的非关键边,从R2倒着再一遍即可判掉R1,得到中间那条链。

//17660kb   1932ms
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=2e5+5;
const LL INF=1e10;

int n,Ans,root,Enum,H[N],to[N<<1],nxt[N<<1],fa[N];
LL Max,dis[N],mx[N],s_mx[N],val[N<<1];
bool is_d[N],Mark[N];

inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}
inline void AddEdge(int u,int v,int w)
{
    to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
    to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
}
void pre_DFS(int x,LL d)
{
    if(d>Max) Max=d, root=x;
    for(int i=H[x]; i; i=nxt[i])
        if(to[i]!=fa[x]) fa[to[i]]=x,pre_DFS(to[i],d+val[i]);
}
void DFS(int x,int f)
{
    for(int v,i=H[x]; i; i=nxt[i])
        if((v=to[i])!=f)
        {
            DFS(v,x);
            if(mx[x]<val[i]+mx[v]) mx[x]=val[i]+mx[v];
            else if(s_mx[x]<val[i]+mx[v]) s_mx[x]=val[i]+mx[v];
        }
}
void DFS_for_Ans(int x,int f,LL d)
{
    for(int i=H[x]; i; i=nxt[i])
            if(to[i]!=f&&is_d[to[i]])
                if(s_mx[x]+d>=Max) {Mark[x]=1/*在此断开*/; return;}
    for(int i=H[x]; i; i=nxt[i])
        if(to[i]!=f&&is_d[to[i]])
            DFS_for_Ans(to[i],x,d+val[i]);
}

int main()
{
//  freopen("diameter.in","r",stdin);
//  freopen("diameter.out","w",stdout);

    n=read();
    for(int u,v,w,i=1; i<n; ++i) u=read(),v=read(),w=read(),AddEdge(u,v,w);
    Max=-INF, pre_DFS(1,0);
    int u=root,v;
    Max=-INF, fa[u]=0, pre_DFS(u,0), v=root;
    while(root!=u) is_d[root]=1,root=fa[root];
    is_d[root]=1;

    DFS(u,-1), DFS_for_Ans(u,-1,0);
    memset(mx,0,sizeof mx), memset(s_mx,0,sizeof s_mx);
    DFS(v,-1), DFS_for_Ans(v,-1,0);
    for(bool f=0; v!=u; v=fa[v],Ans+=f)
        if(Mark[v]) f^=1;
    printf("%I64d\n%d",Max,Ans);

    return 0;
}

反思

考试代码

T1

#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define mod (100005)
typedef long long LL;
const int N=1e6+7;

LL P,A,B,X,pur;
bool vis[500];

struct Hash
{
    int H[N],Enum,nxt[N],to[N],res[N],val[N];
    void Init(){
        Enum=0, memset(H,0,sizeof H);
    }
    void AddEdge(int id,int v)
    {
        int x=v%mod;
        for(int i=H[x]; i; i=nxt[i])
            if(val[i]==v) {to[i]=id; return;}
        to[++Enum]=id, nxt[Enum]=H[x], H[x]=Enum, val[Enum]=v;
    }
    int Query(int v)
    {
        for(int i=H[v%mod]; i; i=nxt[i])
            if(val[i]==v) return to[i];
        return -1;
    }
}hs;
inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
int Spec1()
{
    memset(vis,0,sizeof vis);
    for(int tm=1; !vis[X]; X=(A*X+B)%P,++tm)
        if(X==pur) return tm;
        else vis[X]=1;
    return -1;
}
int gcd(int x,int y){
    return y?gcd(y,x%y):x;
}
void Ex_gcd(int a,int b,int &g,LL &x,LL &y){
    if(!b) x=1ll,y=0ll,g=a;
    else Ex_gcd(b,a%b,g,y,x),y-=a/b*x;
}
int Spec2()
{
    if(X==pur) return 1;
    int R=(pur-X%P+P)%P,gcd; LL x,y;
    Ex_gcd(B,P,gcd,x,y);
    if(R%gcd) return -1;
    x=1ll*x*(R/gcd)%P;
    P/=gcd;
    return (x%P+P)%P+1;
}
LL inv(int v,int p){
    LL x,y;int g; Ex_gcd(v,p,g,x,y);
    return (x%p+p)%p;
}
LL FP(LL x,int k)
{
    LL t=1;
    for(; k; k>>=1,x=x*x%P)
        if(k&1) t=x*t%P;
    return t;
}
int BSGS()
{
    if(gcd(A,P)!=1) return -2;
    hs.Init();
    int m=ceil(sqrt(P-1));
    LL t=pur%P,AM;
    for(int i=0; i<=m; ++i,t=t*A%P) hs.AddEdge(i,t);
    t=AM=FP(A,m);
    for(int res,i=1; i<=m; ++i,t=t*AM%P)
        if((res=hs.Query(t))!=-1) return (1ll*i*m-res)%P;
    return -2;
}
int Spec3()
{
    if(X==pur) return 1;
    pur=pur*inv(X,P)%P;
    return BSGS()+1;
}

int main()
{
    freopen("random.in","r",stdin);
    freopen("random.out","w",stdout);

    int T=read();
    while(T--)
    {
        P=read(),A=read(),B=read(),X=read()%P,pur=read();
        if(P<=100) printf("%d\n",Spec1());
        else if(A==1) printf("%d\n",Spec2());
        else if(!B) printf("%d\n",Spec3());
    }
    return 0;
}/*
1 9 1 6 1 4
*/

T2

样例LCT哪RE不知道。。没改

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=8e4+5;

int n,m;
inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}
#define lson son[x][0]
#define rson son[x][1]
namespace LCT
{
    int fa[N],son[N][2],val[N],sz[N],sk[N];
    bool tag[N];
    inline void Update(int x){
        sz[x]=sz[lson]+sz[rson]+1;
    }
    inline bool n_root(int x){
        return son[fa[x]][0]==x||son[fa[x]][1]==x;
    }
    inline void Rev(int x){
        std::swap(lson,rson), tag[x]^=1;
    }
    inline void PushDown(int x){
        if(tag[x]) Rev(lson),Rev(rson),tag[x]=0;
    }
    void Rotate(int x)
    {
        int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
        if(n_root(a)) son[b][son[b][1]==a]=x;
        if(son[x][r]) fa[son[x][r]]=a;
        fa[a]=x, fa[x]=b, son[a][l]=son[x][r], son[x][r]=a;
        Update(a);
    }
    void Splay(int x)
    {
        int t=1,a=x,b; sk[1]=x;
        while(n_root(a)) sk[++t]=a=fa[a];
        while(t) PushDown(sk[t--]);
        while(n_root(x))
        {
            a=fa[x], b=fa[a];
            if(n_root(a)) Rotate(son[a][1]==x^son[b][1]==a?x:a);
            Rotate(x);
        }
        Update(x);
    }
    void Access(int x){
        for(int pre=0; x; x=fa[pre=x])
            Splay(x), rson=pre, Update(x);
    }
    void Make_root(int x){
        Access(x), Splay(x), Rev(x);
    }
    void Split(int x,int y){
        Make_root(x), Access(y), Splay(y);
    }
    void Link(int x,int y){
        Make_root(x), fa[x]=y;
    }
}
namespace Spec
{
    int root[N],cnt,A[N],ref[N],Enum,H[N],to[N<<1],nxt[N<<1],top[N],dep[N],sz[N],fa[N],sn[N];
    bool vis[N];
    inline void AddEdge(int u,int v)
    {
        to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
        to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    struct Seg_tree
    {
        int tot,sum[N*18],son[N*18][2];
        void Insert(int x,int &y,int l,int r,int p)
        {
            sum[y=++tot]=sum[x]+1;
            if(l<r)
            {
                int m=l+r>>1;
                if(p<=m) son[y][1]=rson, Insert(lson,son[y][0],l,m,p);
                else son[y][0]=lson, Insert(rson,son[y][1],m+1,r,p);
            }
        }
        int Query(int x,int y,int z,int w,int l,int r,int k)
        {
            if(l==r) return l;
            int delta=sum[lson]+sum[son[y][0]]-sum[son[z][0]]-sum[son[w][0]];
            if(delta>=k) return Query(lson,son[y][0],son[z][0],son[w][0],l,l+r>>1,k);
            return Query(rson,son[y][1],son[z][1],son[w][1],(l+r>>1)+1,r,k-delta);
        }
    }t;
    int Find(int x,int r)
    {
        int l=1,mid;
        while(l<r)
            if(ref[mid=l+r>>1]>=x) r=mid;
            else l=mid+1;
        return l;
    }
    void Discrete()
    {
        cnt=1;
        for(int i=2; i<=n; ++i)
            if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
        for(int i=1; i<=n; ++i) A[i]=Find(A[i],cnt);
    }
    void DFS1(int x)
    {
        int mx=0; sz[x]=1;
        for(int v,i=H[x]; i; i=nxt[i])
            if((v=to[i])!=fa[x])
            {
                dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
                if(sz[v]>mx) mx=sz[v],sn[x]=v;
            }
    }
    void DFS2(int x,int tp)
    {
        top[x]=tp;
        if(sn[x])
        {
            DFS2(sn[x],tp);
            for(int i=H[x]; i; i=nxt[i])
                if(to[i]!=fa[x]&&to[i]!=sn[x]) DFS2(to[i],to[i]);
        }
    }
    void DFS(int x)
    {
        t.Insert(root[fa[x]],root[x],1,cnt,A[x]), vis[x]=1;
        for(int i=H[x]; i; i=nxt[i])
            if(to[i]!=fa[x]) fa[to[i]]=x, DFS(to[i]);
    }
    int LCA(int u,int v)
    {
        while(top[u]!=top[v])
        {
            if(dep[top[u]]<dep[top[v]]) std::swap(u,v);
            u=fa[top[u]];
        }
        return dep[u]<dep[v]?u:v;
    }
    void Solve(int T)
    {
        for(int i=1; i<=n; ++i) ref[i]=A[i]=read();
        std::sort(ref+1,ref+1+n), Discrete();
        for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v);
        for(int i=1; i<=n; ++i) if(!vis[i]) DFS(i);
        for(int i=1; i<=n; ++i) if(!sz[i]) DFS1(i),DFS2(i,i);
        int ans=0,x,y,k,w; char opt[3];
        while(T--)
        {
            scanf("%s",opt), x=read()^ans, y=read()^ans,k=read()^ans;
            w=LCA(x,y), printf("%d\n",ans=ref[t.Query(root[x],root[y],root[w],root[fa[w]],1,cnt,k)]);
        }
    }
}
namespace Violence
{
    int A[500],Enum,H[500],to[1000],nxt[1000],tmp[1000],pre[1000];
    bool vis[500];
    inline void AddEdge(int u,int v)
    {
        to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
        to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    void DFS(int x,int y,int f)
    {
        if(x!=y)
            for(int i=H[x]; i; i=nxt[i])
                if(to[i]!=f) pre[to[i]]=x, DFS(to[i],y,x);
    }
    int Query(int x,int y,int k)
    {
        DFS(x,y,-1);
        tmp[0]=0;
        while(y!=x) tmp[++tmp[0]]=A[y],y=pre[y];
        tmp[++tmp[0]]=A[x];
        std::sort(tmp+1,tmp+1+tmp[0]);
        return tmp[k];
    }
    void Solve(int T)
    {
        for(int i=1; i<=n; ++i) A[i]=read();
        for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),AddEdge(u,v);
        int ans=0,x,y,k; char opt[3];
        while(T--)
        {
            scanf("%s",opt), x=read()^ans, y=read()^ans;
            if(opt[0]=='Q') k=read()^ans, printf("%d\n",ans=Query(x,y,k));
            else AddEdge(x,y);
        }
    }
}

int main()
{
    freopen("forest.in","r",stdin);
    freopen("forest.out","w",stdout);

    int test=read(),T;
    n=read(),m=read(),T=read();
    if(test==1||test==2) {Violence::Solve(T); return 0;}
    if((test>=3 && test<=9)||(test>=14 && test<=17)) {Spec::Solve(T);return 0;}
    for(int i=1; i<=n; ++i) LCT::val[i]=read(),LCT::sz[i]=1;
    for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),LCT::Link(u,v);
    int ans=0,x,y,k; char opt[3];
    while(T--)
    {
        scanf("%s",opt), x=read()^ans, y=read()^ans;
        if(opt[0]=='Q') k=read()^ans, LCT::Split(x,y);
        else LCT::Link(x,y);
    }
    return 0;
}

T3

想写树剖没时间了(枚举删边就行啊。。)

#include <cstdio>
#include <cctype>
#define gc() getchar()
typedef long long LL;
const int N=2e5+5;
const LL INF=1e10;

int n,root,Enum,H[N],to[N<<1],nxt[N<<1],val[N<<1];
LL Max;

inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}
inline void AddEdge(int u,int v,int w)
{
    to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, val[Enum]=w;
    to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum, val[Enum]=w;
}
void DFS(int x,int f,LL d)
{
    if(d>Max) Max=d, root=x;
    for(int i=H[x]; i; i=nxt[i])
        if(to[i]!=f) DFS(to[i],x,d+val[i]);
}
namespace Sub
{
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1

    int dep[N],sz[N],son[N],son_v[N],top[N],cnt,pos[N],fa[N];
    struct Seg_tree
    {
        int sum[N],A[N],tag[N],id[N];
        inline void PushUp(int rt){
            sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        }
        inline void Add(int x,int v){
            sum[x]+=v, tag[x]+=v;
        }
        void Build(int l,int r,int rt)
        {
            if(l==r) sum[rt]=A[l], id[l]=rt;
            else if(l<r)
            {
                int m=l+r>>1;
                Build(lson), Build(rson);
                PushUp(rt);
            }
        }
        void Modify(int l,int r,int rt,int L,int R)
        {
            if(L<=l&&r<=R) Add(rt,1);
            else
            {
                int m=l+r>>1;
                if(L<=m) Modify(lson,L,R);
                if(m<R) Modify(rson,L,R);
                PushUp(rt);
            }
        }
    }t;
    void DFS1(int x)
    {
        sz[x]=1; int mx=0;
        for(int v,i=H[x]; i; i=nxt[i])
            if((v=to[i])!=fa[x])
            {
                fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
                if(mx<sz[v]) mx=sz[v],son[x]=v,son_v[x]=i;
            }
    }
    void DFS2(int x,int tp)
    {
        top[x]=tp;
        if(son[x])
        {
            DFS2(son[x],tp), t.A[pos[son_v[x]]=++cnt]=val[son_v[x]];
            for(int i=H[x]; i; i=nxt[i])
                if(to[i]!=fa[x] && to[i]!=son[x])
                    DFS2(to[i],to[i]);
        }
    }
    void Solve()
    {
        DFS1(1), DFS2(1,1);
        for(int i=1; i<=n; ++i) ;
        
    }
}

int main()
{
    freopen("diameter.in","r",stdin);
    freopen("diameter.out","w",stdout);

    n=read();
    for(int u,v,w,i=1; i<n; ++i) u=read(),v=read(),w=read(),AddEdge(u,v,w);
    Max=-INF, DFS(1,-1,0);
    int u=root,v;
    Max=-INF, DFS(u,-1,0), v=root;
    printf("%I64d\n",Max);
//  Sub::Solve();
    printf("233");

    return 0;
}

以上是关于SDOI2013 R1 Day1的主要内容,如果未能解决你的问题,请参考以下文章

SDOI2011 第2轮 DAY1消防 [解题报告]

BZOJ 4598SDOI 2016 Round2 Day1 T3模式字符串

BZOJ4513~4518 SDOI2016 R1 题解

SDOI2017 Round1 Day1 题解 (BZOJ4816 BZOJ4817 BZOJ4818)

JSOI2018R1(九省联考R1)游记

[SDOI2016Round1]解题报告