2018.8.9提高B组模拟考试

今天连续3道题都出锅...无F♂A可说

T1 题意简述:jzoj5775

   解题思路:还算简单...

             考虑先暴力算出(1,1)的魔音值,然后递推。

             发现 (x,y)->(x+1,y) 魔音值增加了1~x行中起始点的数量,减少了x+1~n行中起始点的数量。

                  (x,y)->(x-1,y) 魔音值增加了x~n行中起始点的数量,减少了1~x-1行中起始点的数量。

                  (x,y)->(x,y+1) 魔音值增加了1~y列中起始点的数量,减少了y+1~n列中起始点的数量。

                  (x,y)->(x,y-1) 魔音值增加了y~n列中起始点的数量,减少了1~y-1列中起始点的数量。

             发现可以求每行和每列的前缀和,可以把时间复杂度压到O(2n)。

             有细心的观众可能会说:z呢?

             emmm...由于出题人乱出数据,导致所有数据点的z都默认为1。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
ll n,m,k,sumx[100001],sumy[100001],sum;
int main()
{
    freopen("shuru.in","r",stdin);
    freopen("shuru.out","w",stdout);
    scanf("%lld%lld%lld",&n,&m,&k);
    for(ll i=1;i<=m;i++)
    {
        ll u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        sumx[u]++;
        sumy[v]++;
        sum+=w;
    }
    for(ll i=1;i<=n;i++)
        sum+=sumx[i]*(i-1)+sumy[i]*(i-1);
    for(ll i=2;i<=n;i++)
        sumx[i]+=sumx[i-1],sumy[i]+=sumy[i-1];
    ll xsum=sum,ysum=sum,mnx=sum,ansx=1,mny=sum,ansy=1;
    for(ll i=2;i<=n;i++)
    {
        xsum+=2*sumx[i-1]-sumx[n];
        if(xsum<mnx) mnx=xsum,ansx=i;
        ysum+=2*sumy[i-1]-sumy[n];
        if(ysum<mny) mny=ysum,ansy=i;
    }
    printf("%lld\n%lld %lld\n",mnx+mny-sum,ansx,ansy);
    return 0;
}

T2 题意简述:jzoj5776

   解题思路:和第一题基本相同。

             先dfs求出一个点的结果,同时把每个点的子树大小算出。

             然后dfs,每次查询到一个点时修改它与它父亲的子树大小及边权,然后算出这个点的结果。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
ll n,mn=INF,pnt,cnt,head[700001],rdc[700001],siz[700001],ans[700001];
struct uio{
    ll nxt,to,val;
}edge[1400001];
void add(ll x,ll y,ll z)
{
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;
    edge[cnt].val=z;
    head[x]=cnt;
}
ll dfs(ll x,ll fa)
{
    siz[x]=1;
    ll tmp=0;
    for(ll i=head[x];i;i=edge[i].nxt)
    {
        ll y=edge[i].to;
        if(y==fa) continue;
        tmp+=dfs(y,x)+edge[i].val*siz[y];
        siz[x]+=siz[y];
    }
    return tmp;
}
void dt(ll x,ll fa)
{
    for(ll i=head[x];i;i=edge[i].nxt)
    {
        ll y=edge[i].to;
        if(y==fa) continue;
        ans[y]=ans[x]-edge[i].val*siz[y];
        siz[x]-=siz[y],siz[y]+=siz[x];
        edge[i].val+=rdc[x]-rdc[y];
        ans[y]+=edge[i].val*siz[x];
        if(ans[y]<mn) mn=ans[y],pnt=y;
        if(ans[y]==mn&&y<pnt) pnt=y;
        dt(y,x);
        siz[y]-=siz[x],siz[x]+=siz[y];
        edge[i].val+=rdc[y]-rdc[x];
    }
}
int main()
{
    freopen("yggdrasil.in","r",stdin);
    freopen("yggdrasil.out","w",stdout);
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++)
        scanf("%lld",&rdc[i]);
    for(ll i=1;i<n;i++)
    {
        ll u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w-rdc[u]);
        add(v,u,w-rdc[v]);
    }
    ans[1]=dfs(1,0),mn=ans[1],pnt=1;
    dt(1,0);
    printf("%lld\n%lld\n",pnt,mn);
    return 0;
}

T3 题意简述:jzoj5786

   解题思路:很...麻...烦...

             倍增LCA+线段树维护 <-- 这是出题人的思路。

             由Menteur_Hxy大佬亲身试验,倍增是会T的

             由ErkkiErkko大佬亲身试验,set也是会T的

             由本蒟蒻亲身试验,就算用树剖+线段树,也是会RE的。

             ......

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<set>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,cnt,tot,head[800001];
int hvyson[800001],fa[800001],siz[800001],dep[800001],top[800001],dfsno[800001],vis[800001],mp[800001];
int num[3200001];
struct uio{
    int nxt,to;
}edge[1600001];
//set<int> st;
//set<int>::iterator it;
void add(int x,int y)
{
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;
    head[x]=cnt;
}
void dfs1(int x,int f,int depth)
{
    dep[x]=depth;
    fa[x]=f;
    siz[x]=1;
    int maxson=-1;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(y==f)
            continue;
        dfs1(y,x,depth+1);
        siz[x]+=siz[y];
        if(siz[y]>maxson)
        {
            hvyson[x]=y;
            maxson=siz[y];
        }
    }
}
void dfs2(int x,int topf)
{
    dfsno[x]=++tot;
    mp[tot]=x;
    top[x]=topf;
    if(!hvyson[x])
        return;
    dfs2(hvyson[x],topf);
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        if(y==fa[x]||y==hvyson[x])
            continue;
        dfs2(y,y);
    }
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]? x:y;
}
void revise(int now,int l,int r,int x,int y)
{
    if(l==r)
    {
        num[now]+=y;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid) revise(now<<1,l,mid,x,y);
    else revise(now<<1|1,mid+1,r,x,y);
    num[now]=num[now<<1]+num[now<<1|1];
}
int query(int now,int l,int r,int x)
{
    if(l==r&&num[now]) return 1;
    else if(l==r&&!num[now]) return 0;
    int mid=(l+r)>>1;
    if(x<=mid) return query(now<<1,l,mid,x);
    else return query(now<<1|1,mid+1,r,x);
}
int query1(int now,int l,int r,int L,int R)
{
    if(!num[now]) return INF;
    if(l==r) return l;
    if(L<=l&&r<=R)
    {
        int mid=(l+r)>>1;
        if(num[now<<1|1]) return query1(now<<1|1,mid+1,r,L,R);
        else return query1(now<<1,l,mid,L,R);
    }
    int mid=(l+r)>>1;
    if(mid>=R) return query1(now<<1,l,mid,L,R);
    else
    {
        int tmp=INF;
        if(num[now<<1|1]) tmp=query1(now<<1|1,mid+1,r,L,R);
        if(tmp!=INF) return tmp;
        else return query1(now<<1,l,mid,L,R);
    }
}
int query2(int now,int l,int r,int L,int R)
{
    if(!num[now]) return INF;
    if(l==r) return l;
    if(L<=l&&r<=R)
    {
        int mid=(l+r)>>1;
        if(num[now<<1]) return query2(now<<1,l,mid,L,R);
        else return query2(now<<1|1,mid+1,r,L,R);
    }
    int mid=(l+r)>>1;
    if(mid+1<=L) return query2(now<<1|1,mid+1,r,L,R);
    else
    {
        int tmp=INF;
        if(num[now<<1]) tmp=query2(now<<1,l,mid,L,R);
        if(tmp!=INF) return tmp;
        else return query2(now<<1|1,mid+1,r,L,R);
    }
}
int main()
{
    freopen("watch.in","r",stdin);
    freopen("watch.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
    {
        int u;
        scanf("%d",&u);
        add(i+1,u),add(u,i+1);
    }
    dfs1(1,0,1),dfs2(1,1);
    for(int i=1;i<=m;i++)
    {
        int u;
        scanf("%d",&u);
        if(u>0&&!vis[u]) {revise(1,1,n,dfsno[u],1);vis[u]=1;continue;}
        else if(u>0&&vis[u]) {revise(1,1,n,dfsno[u],-1);vis[u]=0;continue;}
        if(!num[1]) {printf("0\n");continue;}
        u=-u;
        int c=query(1,1,n,dfsno[u]);
        if(c) {printf("%d\n",u);continue;}
        int a=query1(1,1,n,1,dfsno[u]-1);
        int b=query2(1,1,n,dfsno[u]+1,n);
        if(a!=INF) a=lca(u,mp[a]);
        if(b!=INF) b=lca(u,mp[b]);
        if(b==INF) printf("%d\n",a);
        else if(a==INF) printf("%d\n",b);
        else printf("%d\n",(dep[a]>dep[b]? a:b));
//        if(u>0&&!vis[u]) {st.insert(dfsno[u]);vis[u]=1;continue;}
//        else if(u>0&&vis[u])  {st.erase(dfsno[u]);vis[u]=0;continue;}
//        if(st.empty()) {printf("0\n");continue;}
//        u=-u;
//        if(st.count(u)) {printf("%d\n",u);continue;}
//        it=st.upper_bound(dfsno[u]);
//        if(it!=st.end())
//        {
//            a=lca(u,mp[*it]);
//            if(it==st.begin())
//                {printf("%d\n",a);continue;}
//            it--;
//            b=lca(u,mp[*it]);
//            printf("%d\n",(dep[a]>dep[b]? a:b));
//            continue;
//        }
//        it--;
//        b=lca(u,mp[*it]);
//        printf("%d\n",b);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/water-radish/p/9452260.html
今日推荐