ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[游记]暑假集训4-2022.8.16

2022-08-16 20:34:36  阅读:155  来源: 互联网

标签:ch ipt 16 int top WR 2022.8 include 集训


今天还行?不过挂了 $85$ 分

A. 打地鼠

场切签到题

 

 

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=3010,INF=1099588621776;
int n,k;
int dp[WR][WR];
int ans;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+ch-'0';
        ch=getchar();
    }
    return s*w;
}
signed main(){
    n=read(),k=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%1lld",&dp[i][j]);
            dp[i][j]+=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1];
        }
    }
    for(int i=k;i<=n;i++){
        for(int j=k;j<=n;j++){
            ans=max(ans,dp[i][j]-dp[i-k][j]-dp[i][j-k]+dp[i-k][j-k]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

B. 竞赛图

首先这个数据范围是 $2^n$ 的;

然后我们考虑枚举每一个子图的出边,状态压缩地存储

显然对于一张图,我们可以割下一个节点,形成另外一张图

而新图的出边可以由子图和这个点的边按位与得来(后面有用)

也就是说图中必须每一个点都指向图外的一个点才存在这个图向这个点的连边

然后我们考虑如何计算答案,像是一个欧拉筛

首先如果一个图没有被打标记那么它是一个强连通分量

然后我们考虑这个强连通分量的出边,这些边显然都连接着点,设点的集合为 $T$

只考虑强连通分量和点集中的点,由于这些点没有连入强连通分量的边,因此这些点显然不能和强连通分量结合形成新的强连通分量

直接打标记就行了,复杂度是 $\Theta(2^n)$ 的

 

#include<cstdio>
#include<cstring>
#include<string>
#include<stack>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=17010000,INF=1099588621776;
//tarjan显然不可行
//对着这2e8的数组陷入沉思
int n,edge[WR];
bool vis[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+ch-'0';
        ch=getchar();
    }
    return s*w;
}
int lowbit(int x){
    return x&(-x);
}
void binary(int x){
    if(x>=2) binary(x/2);
    printf("%lld",x%2);
}
signed main(){
    int t=read();
    while(t--){
        n=read();int ans=0;
        memset(edge,0,sizeof(edge));
        edge[0]=(1<<n)-1;
        memset(vis,true,sizeof(vis));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int tmp=read();
                if(tmp) edge[1<<(i-1)]|=(1<<(j-1));
            }
        }
        for(int S=1;S<(1<<n);S++){
            int S1=lowbit(S);
            edge[S]=(edge[S1]&edge[S^S1]);
        }
        for(int S=1;S<(1<<n);S++){
            if(vis[S]){
                // binary(edge[S]);printf("\n");
                for(int i=edge[S];i;i=((i-1)&edge[S])){
                    // binary(i);printf(" ");binary(S);printf(" ");binary(S|i);printf("\n");
                    vis[S|i]=false; 
                }
            }
        }
        for(int S=0;S<(1<<n);S++) if(vis[S]) ans++;
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

 

 C. 糖果

咕咕咕

 

D. 树

挂分:85

挂分原因:链顶的父亲不是 $top[fa[x]]$ !!!!!

这,如果做过 染色 这个树剖还是挺显然的

问题在于染色让维护的是点而这道题是边

不妨打上时间戳,如果一条边的两个端点时间戳不同那么它就是黑边,否则是白边

注意起始全为黑边

 

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=300100,INF=1099588621776;
struct Edge{
    int pre,to;
};
struct Tree{
    int l,r,val,lzy;
    int lval,rval;
    Tree(){l=r=lzy=val=lval=rval=0;}
};
struct SegmentTree{
    Tree tree[WR<<3];
    void pushup(int k){
        tree[k].lval=tree[k<<1].lval,tree[k].rval=tree[k<<1|1].rval;
        tree[k].val=tree[k<<1].val+tree[k<<1|1].val;
        // printf("%lld %lld %lld %lld\n",tree[k<<1].val,tree[k<<1|1].val,tree[k<<1].rval,tree[k<<1|1].lval);
        if(tree[k<<1].rval!=tree[k<<1|1].lval) tree[k].val++;
    }
    void pushdown(int k){
        // printf("%lld %lld\n",tree[k].l,tree[k].r);
        tree[k<<1].val=tree[k<<1|1].val=0;
        tree[k<<1].lzy=tree[k<<1|1].lzy=tree[k].lzy;
        tree[k<<1].lval=tree[k<<1].rval=tree[k].lzy;
        tree[k<<1|1].lval=tree[k<<1|1].rval=tree[k].lzy;
        tree[k].lzy=0;
    }
    void build(int k,int l,int r){
        // printf("%lld %lld %lld\n",k,l,r);
        tree[k].l=l,tree[k].r=r;
        if(l==r){
            tree[k].lval=tree[k].rval=l;
            return;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        pushup(k);
    }
    void modify(int k,int l,int r,int val){
        if(tree[k].l>=l&&tree[k].r<=r){
            // printf("%lld %lld %lld\n",tree[k].l,tree[k].r,val);
            tree[k].lval=tree[k].rval=val;
            tree[k].lzy=val;tree[k].val=0;
            return;
        }
        if(tree[k].lzy!=0) pushdown(k);
        int mid=(tree[k].l+tree[k].r)>>1;
        if(l<=mid) modify(k<<1,l,r,val);
        if(r>mid) modify(k<<1|1,l,r,val);
        pushup(k);
    }
    int query(int k,int l,int r){
        // printf("%lld %lld %lld %lld\n",k,l,r,tree[k].lzy);
        if(tree[k].l>=l&&tree[k].r<=r){
            return tree[k].val;
        }
        if(tree[k].lzy!=0) pushdown(k);
        int mid=(tree[k].l+tree[k].r)>>1,res=0;
        if(r<=mid) return query(k<<1,l,r);
        if(l>mid) return query(k<<1|1,l,r);
        res=query(k<<1,l,r)+query(k<<1|1,l,r);
        if(tree[k<<1].rval!=tree[k<<1|1].lval) res++;
        return res;
    }
    int getcolor(int k,int pos){
        if(tree[k].l==tree[k].r){
            return tree[k].lval;
        }
        if(tree[k].lzy!=0) pushdown(k);
        int mid=(tree[k].l+tree[k].r)>>1;
        if(pos<=mid) return getcolor(k<<1,pos);
        else return getcolor(k<<1|1,pos);
    }
}segment;
struct Tree_Cut{
    Edge edge[WR<<1];
    int head[WR],tot=0;
    int fa[WR],son[WR],sze[WR],dpt[WR];
    int ipt[WR],rnk[WR],top[WR],cnt;
    void add(int u,int v){
        edge[++tot].pre=head[u];
        edge[tot].to=v;
        head[u]=tot;
    }
    void dfs1(int u,int root){
        dpt[u]=dpt[root]+1;fa[u]=root;
        sze[u]=1;
        for(int i=head[u];i;i=edge[i].pre){
            int v=edge[i].to;
            if(v==root) continue;
            dfs1(v,u);
            sze[u]+=sze[v];
            if(sze[v]>sze[son[u]]) son[u]=v;
        }
    }
    void dfs2(int u,int tp){
        top[u]=tp,ipt[u]=++cnt,rnk[cnt]=u;
        if(son[u]) dfs2(son[u],tp);
        for(int i=head[u];i;i=edge[i].pre){
            int v=edge[i].to;
            if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
        }
    }
    void path_modify(int x,int y,int val){
        // printf("%lld\n",val);
        while(top[x]!=top[y]){
            if(dpt[top[x]]<dpt[top[y]]) swap(x,y);
            // printf("%lld %lld\n",ipt[top[x]],ipt[x]);
            segment.modify(1,ipt[top[x]],ipt[x],val);
            x=fa[top[x]];
        }
        if(ipt[x]>ipt[y]) swap(x,y);
        segment.modify(1,ipt[x],ipt[y],val);
    }
    int path_query(int x,int y){
        int res=0;
        while(top[x]!=top[y]){
            // printf("%lld %lld\n",ipt[top[x]],ipt[top[y]]);
            if(dpt[top[x]]<dpt[top[y]]) swap(x,y);
            // printf("%lld %lld\n",ipt[top[x]],ipt[x]);
            res+=segment.query(1,ipt[top[x]],ipt[x]);
            if(segment.getcolor(1,ipt[top[x]])!=segment.getcolor(1,ipt[fa[top[x]]])) res++;
            x=fa[top[x]];
        }
        if(ipt[x]>ipt[y]) swap(x,y);
        res+=segment.query(1,ipt[x],ipt[y]);
        return res;
    }
}tree;
int n,q;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+ch-'0';
        ch=getchar();
    }
    return s*w;
}
signed main(){
    n=read();int tag=0;
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        tree.add(u,v);tree.add(v,u);
    }
    tree.dfs1(1,0);tree.dfs2(1,1);
    segment.build(1,1,n);
    // for(int i=1;i<=n;i++) printf("%lld ",tree.dpt[i]);
    // for(int i=1;i<(n<<1);i++) printf("%lld %lld %lld\n",segment.tree[i].l,segment.tree[i].r,segment.tree[i].val);
    q=read();
    while(q--){
        int opt=read();
        if(opt==1){
            int x=read(),y=read();
            tag--;
            tree.path_modify(x,y,tag);
            // for(int i=1;i<(n<<1);i++) printf("%lld %lld %lld\n",segment.tree[i].l,segment.tree[i].r,segment.tree[i].val);
        }else{
            // printf("I am here\n");
            int x=read(),y=read();
            printf("%lld\n",tree.path_query(x,y));
        }
    }
    return 0;
}
View Code

 

标签:ch,ipt,16,int,top,WR,2022.8,include,集训
来源: https://www.cnblogs.com/WintersRain/p/16592845.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有