【UOJ摸鱼】UTR #1解题报告

【UOJ摸鱼】UTR #1解题报告

前言

最近刷uoj题,感觉古代大佬们都好强。。。

vfk的数据

链接

http://uoj.ac/problem/9

题解

一个普通的排序题,直接贴代码了。

\(Code\)

#include <bits/stdc++.h>
using namespace std;
int n;
struct ZFC{
    string s;
    int L;
}s[10005];
bool cmp(ZFC A,ZFC B){
    if(A.L==B.L) return A.s<B.s;
    return A.L<B.L;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i) {
        cin>>s[i].s;
        s[i].L=s[i].s.length();
    }
    sort(s+1,s+1+n,cmp);
    for(int i=1;i<=n;++i) cout<<s[i].s<<endl;
    return 0;
} 

pyx的难题

链接

http://uoj.ac/problem/10

题解

如果已知优先级,然后模仿整个过程是\(O(nlogn)\)的。
于是不难想到一个二分答案的\(O(nlog^{2}n)\)的做法。然而过不了。
然后我就卡在这了。。。
“第一问的二分是建立在单调性上的,而有单调性的题,往往可以试着利用扫描的方法去优化。”(题解原话)
感觉这个思路并不新,但经常会忘记有这种方向。。然而确实是很实用的一种思路。
然后把二分换成扫描就降了一个log下来,就能过了。

\(Code\)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=3e5+10;
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*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(LL x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int n;
LL sss,ttt;
struct node{
    int t,s,p,id,v;
    LL L;
}a[N];
bool cmp(node A,node B){
    return A.p<B.p;
}
bool cmp2(node A,node B){
    return A.t<B.t;
}
bool cmp3(node A,node B){
    return A.id<B.id;
}
map<int,int> num,pi;
priority_queue< pair<int,int> > Q;
void J(LL l,LL r,int pp){
    int x=num[pp];
    if(l<sss) l=sss;
    if(r>ttt) r=ttt;
    if(l<=r) a[x].L+=r-l+1; 
}
LL ans[N];
int main(){
    pair<int,int> z;
    n=read();
    for(int i=1;i<=n;++i) {
        a[i].t=read();a[i].s=read();a[i].p=read();
        a[i].id=i;
        if(a[i].p==-1) sss=a[i].t;
    }
    scanf("%lld",&ttt);--ttt;
    sort(a+1,a+1+n,cmp2);
    for(int i=1;i<=n;++i){
        num[a[i].p]=i;a[i].v=i;
    }
    LL now=0,tt;
    for(int i=1;i<=n;++i){
        while(now<a[i].t&&(!Q.empty())){
            z=Q.top();Q.pop();
            tt=min((LL)z.second,(LL)a[i].t-now);
            J(now,now+tt-1,z.first);
            now=now+tt;z.second=z.second-tt;
            if(z.second) Q.push(z);
        }
        if(now<a[i].t) now=a[i].t;
        Q.push(make_pair(a[i].p,a[i].s));
    }
    
    while(!Q.empty()){
        z=Q.top();Q.pop();
        tt=z.second;
        J(now,now+tt-1,z.first);
        now=now+tt;
    }
    sort(a+1,a+1+n,cmp);
    LL w=0;int y;
    for(int i=1;i<=n;++i){
        w=w+a[i].L;
        y=max(1,a[i].p+1);
        if(num[y]) continue;
        if(w==a[1].s) {
            a[1].p=y;break;
        }
    }
    cout<<a[1].p<<endl;
    num[a[1].p]=num[-1];a[1].v=num[-1];
    for(int i=1;i<=n;++i) {
        y=a[i].v;
        while(i!=a[i].v){
            swap(a[i],a[y]);
            y=a[i].v;
        }
    }
    now=0;
    for(int i=1;i<=n;++i){
        while(now<a[i].t&&(!Q.empty())){
            z=Q.top();Q.pop();
            tt=min((LL)z.second,(LL)a[i].t-now);
            now=now+tt;z.second=z.second-tt;
            if(z.second) Q.push(z);
            else{
                ans[a[num[z.first]].id]=now;
            }
        }
        if(now<a[i].t) now=a[i].t;
        Q.push(make_pair(a[i].p,a[i].s));
    }
    while(!Q.empty()){
        z=Q.top();Q.pop();
        tt=z.second;
        now=now+tt;
        ans[a[num[z.first]].id]=now;
    }
    for(int i=1;i<=n;++i) {
        print(ans[i]);putchar(' ');
    }
    puts("");
    return 0;
}

ydc的大树

链接

http://uoj.ac/problem/11

题解

这道题要用到树的中心的概念。
树的任何一个点的最远点一定是某条直径的端点。通过这个性质可以\(O(n)\)找直径。
树的直径可能有多个(这个显然,参考菊花树)。
取某条直径,找到直径的最中间的点,这个点不一定是树的节点,也可能是边上的某点,记这个点是树的中心。
有一个性质:任何一个点走到最远点一定经过中心。
由于中心可以在边上,那样的话那条边的两个端点就必然被经过了。

然后再这道题中,如果我们把中心或中心所在边上的某端点取出来作为根,就会有神奇的性质。
所有黑点到它的好朋友的路径一定经过根节点。
显然,如果把一条路径从根节点分成两段,第一段就是走到根,第二段就是找个最深黑点走。
然后这题就变成了一个大讨论题。。
首先我们考虑如果最后答案是0,那么方案数一定是n-m。
然后我们只考虑能让黑点不高兴的情况。
如果断点是根,这个情况挺好写的不说了。
若最深黑点分布在至少3颗子树中,我们只需考虑每个白点的子树内黑点数即可。
若最深黑点分布在恰好2颗子树中,没有最深黑点的子树像第一种情况来就好,然后剩余两颗子树之间再讨论。
(由于以上两种数据听特殊的,似乎uoj里数据没有上面两种情况)
然后只有一颗子树内有最深黑点时,在这颗子树内的黑点要找的其他“最深点”要另外再找一遍。
如果断点在这颗子树中,我们只需看它是否覆盖到所有最深黑点进行讨论。
如果断点在其他子树中,我们要找到次深黑点再讨论,具体不赘述了,看代码吧。

\(Code\)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+10;
const int INF=1e9;
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*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(LL x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int n,m,cnt=1;
int col[N],bl[N],dis[N],hed[N],las[N];
struct edge{
    int r,nxt,w;
}e[N<<1];
void insert(int u,int v,int w){
    e[++cnt].r=v;e[cnt].nxt=hed[u];hed[u]=cnt;e[cnt].w=w;
}
int rt;
int q[N];
void dij(){
    int l=1,r=1;q[1]=rt;
    fill_n(dis,N,INF);
    dis[rt]=0;
    while(l<=r){
        int y=q[l++];
        for(int i=hed[y];i;i=e[i].nxt){
            if(dis[e[i].r]>dis[y]+e[i].w){
                las[e[i].r]=y;
                dis[e[i].r]=dis[y]+e[i].w;
                q[++r]=e[i].r;
            }
        }
    }
    return;
}
int mxd[N],fa[N],dep[N];
void dfs(int x){
    if(col[x]) mxd[x]=dep[x];
    for(int i=hed[x];i;i=e[i].nxt){
        if(fa[x]!=e[i].r){
            fa[e[i].r]=x;
            dep[e[i].r]=dep[x]+e[i].w;
            dfs(e[i].r);
            mxd[x]=max(mxd[x],mxd[e[i].r]);
        }
    }
}
int mx=0;
int ans1=0,ans2=0;
void upd(int x){
    if(x<=0) return;
    if(x>ans1){ans1=x;ans2=1;}
    else if(x==ans1) ++ans2;
}
int sz[N],son[N];
void getval(int x){
    sz[x]=col[x];
    if(col[x]==1&&dep[x]==mx) son[x]=1;
    for(int i=hed[x];i;i=e[i].nxt){
        if(e[i].r!=fa[x]){
            getval(e[i].r);
            sz[x]+=sz[e[i].r];
            son[x]+=son[e[i].r];
        }
    }
}
void DP(int x,int op,int y,int z){
    for(int i=hed[x];i;i=e[i].nxt){
        if(e[i].r!=fa[x]){
            DP(e[i].r,op,y,z);
        }
    }
    if(col[x]==0){
        if(op==3){upd(sz[x]);return;}
        if(op==2){
            if(son[x]==son[y]) upd(sz[x]+m-sz[y]);
            else upd(sz[x]);
            return;
        }
        if(op==1){
            if(son[x]==son[y]) upd(sz[x]+sz[z]);
            else upd(sz[x]);
            return;
        }
    }
}
int main(){
    int u,v,w;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        bl[i]=read();
        col[bl[i]]=1;
    }
    for(int i=1;i<n;++i){
        u=read();v=read();w=read();
        insert(u,v,w);
        insert(v,u,w);
    }
    rt=bl[1];
    dij();
    for(int i=1;i<=m;++i){
        if(dis[bl[i]]>dis[rt]) rt=bl[i];
    }
    dij();
    u=rt;v=rt;
    for(int i=1;i<=m;++i){
        if(dis[bl[i]]>dis[v]) v=bl[i];
    }
    double D=dis[v]*1.0/2;
    while(dis[las[v]]>=D) v=las[v];
    rt=v;
    dfs(rt);
    for(int i=1;i<=m;++i) mx=max(mx,mxd[bl[i]]);
    int k=0;
    for(int i=hed[rt];i;i=e[i].nxt) if(mxd[e[i].r]==mx) ++k;
    if(k>=3) k=3;
    ans1=0;ans2=n-m;
    if(col[rt]==0)upd(m);
    getval(rt);
    if(k==2){
        u=0;v=0;
        for(int i=hed[rt];i;i=e[i].nxt) {
            if(mxd[e[i].r]==mx){
                if(!u) u=e[i].r;
                else v=e[i].r;
            } 
        }
    }
    for(int i=hed[rt];i;i=e[i].nxt) {
        if(k==3)DP(e[i].r,3,e[i].r,0);
        if(k==2&&mxd[e[i].r]!=mx) DP(e[i].r,3,e[i].r,0);
        if(k==2&&mxd[e[i].r]==mx) DP(e[i].r,1,e[i].r,(e[i].r^u^v));
        if(k==1&&mxd[e[i].r]==mx) DP(e[i].r,2,e[i].r,0);
    }
    if(k==1){
        u=0;v=0;
        for(int i=hed[rt];i;i=e[i].nxt) {
            if(mxd[e[i].r]==mx){
                u=e[i].r;
            } 
        }
        v=mx;
        mx=0;
        for(int i=hed[rt];i;i=e[i].nxt){
            if(mxd[e[i].r]!=v){
                mx=max(mx,mxd[e[i].r]);
            }
        }
        k=0;
        for(int i=hed[rt];i;i=e[i].nxt) if(mxd[e[i].r]==mx) ++k;
        if(mx>0){
            if(k==1){
                for(int i=hed[rt];i;i=e[i].nxt){
                    if(mxd[e[i].r]<mx) DP(e[i].r,3,e[i].r,0);
                }
                getval(rt);
                for(int i=hed[rt];i;i=e[i].nxt){
                    if(mxd[e[i].r]==mx) DP(e[i].r,1,e[i].r,u);
                }
            }
            else{
                for(int i=hed[rt];i;i=e[i].nxt){
                    if(mxd[e[i].r]<=mx) DP(e[i].r,3,e[i].r,0);
                }
            }
        }
    }
    printf("%d %d\n",ans1,ans2);
    return 0;
}
posted @ 2020-09-23 21:30  Iscream-2001  阅读(334)  评论(0编辑  收藏  举报
/* */ /* */