csp-s模拟测试77/78部分题解

 

Day1T2

题解

集合求交,求并维护时间戳,整体+,-维护一个变量

其实都挺套路的,但我考场什么都没想到,竟然还有60

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 3444444
const ll sz=5000000;
ll a[sz];
ll *b=a+2500000;
ll ans,m,opt,mark,n,k,size,T=1;
int main(){
//    freopen("ex_jihe3.in","r",stdin);
//    freopen("zj.out","w",stdout);
    scanf("%lld",&m);
    for(ll i=1;i<=m;i++){
        scanf("%lld",&opt);
        if(opt==1){
            scanf("%lld",&k);
            for(ll i=1;i<=k;i++){
                scanf("%lld",&n);
                if(b[n-mark]!=T){
                    b[n-mark]=T;
                    ans+=n-mark;
                    size++;
                }
            }
        }
        else if(opt==2){
            ++T;ans=0;size=0;
            scanf("%lld",&k);
            for(ll i=1;i<=k;i++){
                scanf("%lld",&n);
                if(b[n-mark]==T-1){
                    b[n-mark]=T;                
                    ans+=n-mark;
                    size++;
//                    printf("n-mark=%lld sz=%lld
",n-mark,size);
                }
            }
        }
        else if(opt==3){
            mark++;
        }
        else if(opt==4){
            mark--;
        }
        printf("%lld
",ans+mark*size);
    }
}
View Code

Day1T3

题解

部分分有一部分是$C_m^2$提示

我们其他也可以这么做,找到每一个极大联通空地同时联通相同颜色每一对都会造成贡献

但是这样会有多个联通的情况

可能会出现最多会出现两个颜色之间四联通,会算重

必须容斥

记录下每个块被那个极大联通空地链接

f1[x][col]记录被x连接颜色为col的情况

f2[x][y][col]记录被x,y两个联通块链接颜色为col的情况

f3[x][y][z][col],f4[w][x][y][z][col]

奇加偶减,f1,f2,f3,f4用map存一下即可

相邻单独考虑

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1111
struct node{
    ll bl1,bl2,bl3,bl4,col;
    node(){}
    node(const ll &a,const ll &b,const ll &c,const ll &d,const ll &e){
        bl1=a,bl2=b,bl3=c,bl4=d,col=e;
    }
    friend bool operator < (const node &a,const node &b){
        if(a.bl1!=b.bl1) return a.bl1<b.bl1;
        if(a.bl2!=b.bl2) return a.bl2<b.bl2;
        if(a.bl3!=b.bl3) return a.bl3<b.bl3;
        if(a.bl4!=b.bl4) return a.bl4<b.bl4;
        return a.col<b.col;
    }
};
map<node,ll> mp;
ll bl[5][A][A],vis[A][A],col[A][A];
ll nowx[5]={0,1,-1,0,0};
ll nowy[5]={0,0,0,1,-1};
ll n,m,k,tim,ans;
void dfs(ll x,ll y){
    vis[x][y]=tim;
    if(col[x][y]){
        if(!bl[1][x][y]) bl[1][x][y]=tim;
        else if(!bl[2][x][y]) bl[2][x][y]=tim;
        else if(!bl[3][x][y]) bl[3][x][y]=tim;
        else if(!bl[4][x][y]) bl[4][x][y]=tim;
        return ;
    }
    for(ll i=1;i<=4;i++){
        ll xnow=nowx[i]+x,ynow=nowy[i]+y;
        if(xnow>=1&&xnow<=n&&ynow>=1&&ynow<=m&&vis[xnow][ynow]!=tim){
            dfs(xnow,ynow);
        }
    }
}
int main(){
//    freopen("ex_link4.in","r",stdin);
    ll kk;
    scanf("%lld%lld%lld",&n,&m,&kk);
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=m;j++)
            scanf("%lld",&col[i][j]);
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=m;j++){
            if(!vis[i][j]&&col[i][j]==0){
                tim++;
                dfs(i,j);
            }
        }
    for(ll i=1;i<=n;i++)
        for(ll j=1;j<=m;j++)
            if(col[i][j]){
                if(bl[1][i][j]){
                    ans+=mp[node(bl[1][i][j],0,0,0,col[i][j])]++;
                }
                if(bl[2][i][j]){
                    ans+=mp[node(bl[2][i][j],0,0,0,col[i][j])]++;
                    ans-=mp[node(bl[1][i][j],bl[2][i][j],0,0,col[i][j])]++;
                }
                if(bl[3][i][j]){
                    ans+=mp[node(bl[3][i][j],0,0,0,col[i][j])]++;
                    ans-=mp[node(bl[2][i][j],bl[3][i][j],0,0,col[i][j])]++;
                    ans-=mp[node(bl[1][i][j],bl[3][i][j],0,0,col[i][j])]++;
                    ans+=mp[node(bl[1][i][j],bl[2][i][j],bl[3][i][j],0,col[i][j])]++;
                }
                if(bl[4][i][j]){
                    ans+=mp[node(bl[4][i][j],0,0,0,col[i][j])]++;
                    ans-=mp[node(bl[1][i][j],bl[4][i][j],0,0,col[i][j])]++;
                    ans-=mp[node(bl[2][i][j],bl[4][i][j],0,0,col[i][j])]++;
                    ans-=mp[node(bl[3][i][j],bl[4][i][j],0,0,col[i][j])]++;
                    ans+=mp[node(bl[1][i][j],bl[2][i][j],bl[4][i][j],0,col[i][j])]++;
                    ans+=mp[node(bl[1][i][j],bl[3][i][j],bl[4][i][j],0,col[i][j])]++;
                    ans+=mp[node(bl[2][i][j],bl[3][i][j],bl[4][i][j],0,col[i][j])]++;
                    ans-=mp[node(bl[1][i][j],bl[2][i][j],bl[3][i][j],bl[4][i][j],col[i][j])]++;
                }
//                printf("%lld bl 4=%lld 3=%lld 2=%lld 1=%lld
",ans,bl[4][i][j],bl[3][i][j],bl[2][i][j],bl[1][i][j]);
            }
//    printf("%lld
",ans);
    for(ll i=1;i<=n;i++)
        for(ll j=2;j<=m;j++)
            if(col[i][j-1]&&col[i][j]&&col[i][j]==col[i][j-1]){
                ll ok=1;
                for(ll k=1;k<=4;k++)
                    for(ll e=1;e<=4;e++)
                        if(bl[k][i][j]&&bl[e][i][j-1]&&bl[k][i][j]==bl[e][i][j-1])
                            ok=0;
                ans+=ok;
            }
    for(ll i=2;i<=n;i++)
        for(ll j=1;j<=m;j++)
            if(col[i-1][j]&&col[i][j]&&col[i][j]==col[i-1][j]){    
            ll    ok=1;
                for(ll k=1;k<=4;k++)
                    for(ll e=1;e<=4;e++)
                        if(bl[k][i][j]&&bl[e][i-1][j]&&bl[k][i][j]==bl[e][i-1][j])
                            ok=0;
            ans+=ok;
        }
    printf("%lld
",ans);
}
View Code

Day2T3

题解

假设环上点为黑点,其他点为白点,我们现在要统计的就是max(白点到最近黑点距离)

假设黑点中深度最小的为B

开这样几个数组ff[x]表示从x走到父亲后能走到最远距离

g[x]表示从x向下走到距离最远是多少

然而可能有最多两个黑点将路径堵塞,所以记录最大值,次大值,次次大值,

黑点即使将最大值次大值堵上,你可以走次次大值

然后贡献可以分为两部分

每个黑点g,最上点ff

这样复杂度仍然会炸

考虑优化求每个黑点g

发现lca路径上除了lca其他点只和一个儿子黑点相邻

q[x]表示从x走到父亲路径上向下走但不经过x达到最远点

然后倍增优化一下

现在贡献变成g[lca],g[x],g[y],q[lca路径上],ff[lca]

分别维护一下

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1111111
ll n,tot=1,tim,m,t;
ll head[A],ver[A],nxt[A],du[211111],deep[A],qjdis[A],zj[A];
ll maxcost[A][25],f[A][25];
ll ans=0;
pair<ll,ll>g[A][3],dis[A],ff[A],q[A][25];
pair<ll,ll>tmp;
void add(ll x,ll y){
    nxt[++tot]=head[x],head[x]=tot,ver[tot]=y;
}
ll lca(ll x,ll y){
    pair<ll,ll> pr;ll now=0;
    pr=make_pair(0,0);    
    if(deep[x]>deep[y]) swap(x,y);
    ll lastx=x,lasty=y;
    for(ll i=t;i>=0;i--){
        if(deep[x]==deep[y]) break;
        if(deep[x]<=deep[f[y][i]]) {
            pr=max(pr,q[y][i]);
            y=f[y][i];
        }
    }
    if(x==y) {
        ll lcq=x;
        return max(pr.first,max(ff[lcq].first,g[lasty][0].first));
    }
    for(ll i=t;i>=0;i--){
        if(f[x][i]!=f[y][i]) {
            pr=max(pr,q[x][i]);
            pr=max(pr,q[y][i]);
            x=f[x][i],y=f[y][i];
        }
    }
    ll lcq=f[x][0];
    if((g[lcq][0].second==x&&g[lcq][1].second==y)||(g[lcq][1].second==x&&g[lcq][0].second==y)){
        now=max(g[lcq][2].first,pr.first);
    }
    else if((g[lcq][0].second==x&&g[lcq][1].second!=y)||(g[lcq][0].second==y&&g[lcq][1].second!=x)){
        now=max(g[lcq][1].first,pr.first);
    }
    else {
        now=max(g[lcq][0].first,pr.first);
    }
    now=max(now,ff[lcq].first);
    now=max(now,max(g[lastx][0].first,g[lasty][0].first));
    return now;
}
pair<ll,ll> dfs1(ll x,ll pre){
    dis[x]=make_pair(0,0);
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        f[y][0]=x;
        deep[y]=deep[x]+1;
        pair<ll,ll> d=dfs1(y,x);
        dis[x]=max(dis[x],d);
    }
    return make_pair(dis[x].first+1,dis[x].second);
}
void dfs2(ll x,ll pre){
    pair<ll,ll> fir,sec,thi,tmp;
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        if((dis[y].first+1)>fir.first){
            thi=sec;sec=fir;fir=make_pair(dis[y].first+1,y);
        }
        else if((dis[y].first+1)>sec.first){
            thi=sec;
            sec=make_pair(dis[y].first+1,y);
        }
        else if((dis[y].first+1)>thi.first){
            thi=make_pair(dis[y].first+1,y);
        }
    }
    g[x][0]=make_pair(fir.first,fir.second);
    g[x][1]=make_pair(sec.first,sec.second);
    g[x][2]=make_pair(thi.first,thi.second);
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        if(dis[y].first+1==fir.first) q[y][0]=sec;
        else q[y][0]=fir;
    }
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        dfs2(y,x);
    }
}
void redfs(ll x,ll pre){
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        ff[y]=ff[x];
        if(y==g[x][0].second)
            ff[y]=max(ff[y],g[x][1]);
        else ff[y]=max(ff[y],g[x][0]);
        ff[y]=make_pair(ff[y].first+1,ff[y].second);
    }
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        redfs(y,x);
    }
}
void dfs3(ll x,ll pre){
    for(ll i=head[x];i;i=nxt[i]){
        ll y=ver[i];
        if(y==pre) continue ;
        dfs3(y,x);
        ans=max(zj[x]+zj[y]+1,ans);
        zj[x]=max(zj[x],zj[y]+1);
    }
}
int main(){
    scanf("%lld",&n);
    t=log(n)/log(2)+1;
    for(ll i=1;i<n;i++){
        ll a,b;
        scanf("%lld%lld",&a,&b);
        add(a,b);
        add(b,a);
    }
    dfs1(1,0);
    dfs2(1,0);
    dfs3(1,0);
    redfs(1,0);
    f[1][0]=1;
    for(ll j=1;j<=t;j++){
        for(ll i=1;i<=n;i++){
            f[i][j]=f[f[i][j-1]][j-1];
            q[i][j]=max(q[f[i][j-1]][j-1],q[i][j-1]);
        }
    }
    scanf("%lld",&m);
    for(ll i=1;i<=m;i++){
        ll a,b;
        scanf("%lld%lld",&a,&b);
        if(a==b){
            printf("%lld
",(ans)/2+1);
            continue ;
        }
        printf("%lld
",lca(a,b));
    }
}
View Code
原文地址:https://www.cnblogs.com/znsbc-13/p/11717557.html