做题日志(2019 1.6~)

这里记录这只菜鸡每天都在做啥水题,不喜勿喷

1.6

1.

https://www.cnblogs.com/ZH-comld/p/10227240.html

2、

https://www.luogu.org/problemnew/show/P1501

zzLCT,而我更zz,维护标记的方式和模板线段树2的方式一样

#include<iostream>
#include<cstdio>
#define N 100002
#define ls ch[x][0]
#define rs ch[x][1]
using namespace std;
typedef long long ll;
const int mod=51061;
int ch[N][2],fa[N],n,q; 
bool rev[N];
ll sum[N],a[N],cheng[N],jia[N],size[N];
char s[2];
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
inline bool ge(int x){return ch[fa[x]][1]==x;}
inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void pushup(int x){sum[x]=(sum[ls]+sum[rs]+a[x])%mod;size[x]=size[ls]+size[rs]+1;}
inline void pushdown(int x){
    if(rev[x]){rev[x]^=1;rev[ls]^=1;rev[rs]^=1;swap(ls,rs);}
    if(cheng[x]!=1){
        (sum[ls]*=cheng[x])%=mod;(sum[rs]*=cheng[x])%=mod;
        (cheng[ls]*=cheng[x])%=mod;(cheng[rs]*=cheng[x])%=mod;
        (jia[ls]*=cheng[x])%=mod;(jia[rs]*=cheng[x])%=mod;
        (a[ls]*=cheng[x])%=mod;(a[rs]*=cheng[x])%=mod;cheng[x]=1;
    }
    if(jia[x]!=0){
        (sum[ls]+=jia[x]*size[ls])%=mod;(sum[rs]+=jia[x]*size[rs])%=mod;
        (jia[ls]+=jia[x])%=mod;(jia[rs]+=jia[x])%=mod;
        (a[ls]+=jia[x])%=mod;(a[rs]+=jia[x])%=mod;jia[x]=0;
    }
}
inline void _pushdown(int x){if(!isroot(x))_pushdown(fa[x]);pushdown(x);}
inline void rotate(int x){
    int y=fa[x],o=ge(x);
    ch[y][o]=ch[x][o^1];fa[ch[y][o]]=y;
    if(!isroot(y))ch[fa[y]][ge(y)]=x;fa[x]=fa[y];
    fa[y]=x;ch[x][o^1]=y;pushup(y);pushup(x);
}
inline void splay(int x){
    _pushdown(x);
    while(!isroot(x)){
        int y=fa[x];
        if(isroot(y))rotate(x);
        else rotate(ge(y)==ge(x)?y:x),rotate(x);
    }
}
inline void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,pushup(x);}
inline void makeroot(int x){access(x);splay(x);rev[x]^=1;}
inline void link(int x,int y){makeroot(x);fa[x]=y;}
inline void split(int x,int y){makeroot(x);access(y);splay(y);}
inline void cut(int x,int y){split(x,y);fa[x]=ch[y][0]=0;pushup(y);}
void dfs(int x){if(ls)dfs(ls);cout<<x<<" ";if(rs)dfs(rs);}
int main(){
    n=rd();q=rd();int x,y,xx,yy,c;
    for(int i=1;i<=n;++i)a[i]=sum[i]=1,cheng[i]=1,size[i]=1;
    for(int i=1;i<n;++i){x=rd();y=rd();link(x,y);}
    while(q--){
        scanf("%s",s);
        if(s[0]=='-'){x=rd();y=rd();xx=rd();yy=rd();cut(x,y);link(xx,yy);}
        else if(s[0]=='+'){
            x=rd();y=rd();c=rd();
            split(x,y);(sum[y]+=c*size[y])%=mod;(jia[y]+=c)%=mod;(a[y]+=c)%=mod;
        }
        else if(s[0]=='*'){
            x=rd();y=rd();c=rd();
            split(x,y);(sum[y]*=c)%=mod;(cheng[y]*=c)%=mod;(jia[y]*=c)%=mod;(a[y]*=c)%=mod;
        }
        else{
            x=rd();y=rd();split(x,y);printf("%lld\n",sum[y]);
        }
    }
    return 0;
}
View Code

3、

https://www.cnblogs.com/ZH-comld/p/10229143.html

4、

https://www.lydsy.com/JudgeOnline/upload/201804/day2(3).pdf

什么垃圾题目,交上去发现和我年轻时写的暴力一个分。。

需要对每个时间点存一个版本,二分的时候就直接用,因为C比较小,所以复制版本还是比较快的。

注意清空一切可能会出锅的地方。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define N 209
using namespace std;
vector<int>vec[N][N];
int T,C,n,m,b[N],s[N],win[N],ans[N],t;
queue<int>q;
inline int rd(){
    int x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
struct DINIC{
  struct edge{int n,to,l;}e[N*40];
  int tot,head[N<<1],deep[N<<1],cur[N<<1];
  DINIC(){tot=1;}
  inline void clear(){tot=1;memset(head,0,sizeof(head));}
  inline void add(int u,int v,int l){
    e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
    e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=0;
  }  
  inline bool bfs(int s,int t){
    memset(deep,0,sizeof(deep));
    memcpy(cur,head,sizeof(head));
    q.push(s);deep[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].n){
            int v=e[i].to;
            if(!deep[v]&&e[i].l){deep[v]=deep[u]+1;q.push(v);}
        }
    }
    return deep[t];
  }
  int dfs(int u,int t,int l){
    if(u==t||!l)return l;
    int f,flow=0;
    for(int &i=cur[u];i;i=e[i].n){
        int v=e[i].to;
        if(deep[v]==deep[u]+1&&(f=dfs(v,t,min(l,e[i].l)))){
            e[i].l-=f;e[i^1].l+=f;l-=f;flow+=f;
            if(!l)break; 
        }
    }
    return flow;
  }
  inline int maxflow(int s,int t){
       if(bfs(s,t))return dfs(s,t,2e9);
    return 0;
  }
}dinic[N],efs;
inline int check(int mid,int id){
    efs=dinic[mid-1];
    for(int i=1;i<=s[id];++i){
      for(int j=0;j<vec[id][i].size();++j)efs.add(id,vec[id][i][j]+n,1);  
    }
    if(efs.bfs(0,t))return 1;else return 0;
}
int main(){
    T=rd();C=rd();
    while(T--){
        n=rd();m=rd();int x;t=n+m+1;
        for(int i=1;i<=m;++i)b[i]=rd(),dinic[0].add(i+n,t,b[i]);
        for(int i=1;i<=n;++i)dinic[0].add(0,i,1); 
        for(int i=1;i<=n;++i)
          for(int j=1;j<=m;++j){
            x=rd();if(x)vec[i][x].push_back(j);
        }
        for(int i=1;i<=n;++i)s[i]=rd();
        for(int i=1;i<=n;++i){
            win[i]=m+1;ans[i]=i;
            for(int j=1;j<=m;++j){
                dinic[i]=dinic[i-1];
                for(int k=0;k<vec[i][j].size();++k)dinic[i].add(i,vec[i][j][k]+n,1);
                if(dinic[i].maxflow(0,t)){win[i]=j;break;}
            }
            int l=1,r=i;
            while(l<=r){
                int mid=(l+r)>>1;
                if(check(mid,i))ans[i]=i-mid,l=mid+1;else r=mid-1;
            }
        }
        for(int i=1;i<=n;++i)printf("%d ",win[i]);puts("");
        for(int i=1;i<=n;++i)printf("%d ",ans[i]);puts("");
        for(int i=1;i<=n;++i)for(int j=0;j<=m;++j)vec[i][j].clear();
        dinic[0].clear();
    }
    return 0;
}
View Code

 5、

现在在看这题发现是道大水题,把轮廓线状压一下,每次合法的操作就是把状态里的10换成01,然后整个操作就是从n个1m个0到m个0n个1,这点规律还是很好发现的。

然后,思博记搜。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 11
using namespace std;
int dp[1<<21],n,m,a[2][N][N],x,inf;
inline int rd(){
    int x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
inline void pt(int s){
    for(int i=0;i<n+m;++i)printf("%d ",(s&(1<<i))!=0);cout<<endl;
}
void dfs(int s,int now){
    if(dp[s]!=inf)return;
    if(now)dp[s]=2e9;
    int dx=n,dy=0;
    for(int i=0;i<m+n-1;++i){
       if((s&(1<<i))&&(!(s&(1<<i+1)))){
        int y=s^(1<<i)^(1<<i+1);dfs(y,now^1);
        if(!now)dp[s]=max(dp[s],a[now][dx][dy+1]+dp[y]);
        else dp[s]=min(dp[s],-a[now][dx][dy+1]+dp[y]);
       }
      if(s&(1<<i))dx--;else dy++;
    }
}
int main(){
    n=rd();m=rd();
    memset(dp,-0x3f,sizeof(dp));
    inf=dp[0];
    for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)a[0][i][j]=rd();
    for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)a[1][i][j]=rd();
    int s=0;
    for(int i=0;i<n;++i)s+=(1<<i);
    x=0;
    for(int i=m;i<n+m;++i)x+=(1<<i);
    dp[x]=0;
    dfs(s,0);
    printf("%d",dp[s]);
    return 0;
} 
View Code

猜你喜欢

转载自www.cnblogs.com/ZH-comld/p/10229146.html
1.6