杂题(大部分网络流+暴力)

[HEOI2016/TJOI2016]树
写了个树剖。。。,记一下链头
跑得比暴力还慢,这数据也是太弱了。。。。。。

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#define ll long long
const int M=210000,mod=(int)1e9+7;
int nex[M],head[M],to[M],dep[M],size[M],son[M],id[M],cnt,tot,f[M],flag[M],fl[M],top[M],n,m;
void add(int x,int y){nex[++tot]=head[x];to[tot]=y;head[x]=tot;}
void dfs1(int x){size[x]=1;
    for(int i=head[x],tmp;i;i=nex[i]){
        if(dep[tmp=to[i]]) continue;
        dep[tmp]=dep[x]+1;f[tmp]=x;dfs1(tmp);
        size[x]+=size[tmp];son[x]=(size[tmp]>size[son[x]])?tmp:son[x];
    }
}
void dfs2(int x,int fa){
    id[x]=++cnt;top[x]=fa;
    if(!son[x]) return;
    dfs2(son[x],fa);
    for(int i=head[x];i;i=nex[i])
    if(!id[to[i]]) dfs2(to[i],to[i]);
}
int query(int x){
    while(!flag[top[x]]) x=f[top[x]];
    while(!fl[x])x=f[x];return x;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x); 
    flag[1]=fl[1]=1,dep[1]=1,dfs1(1),dfs2(1,1);
    while(m--){char s[2];int x;scanf("%s%d",s,&x);
        if(s[0]=='C') fl[x]=1,flag[top[x]]=1;
        else printf("%d\n",query(x));
    }
}

若果没有限制,答案就是(sum(1~n))^m
但有的不能取,直接去掉就可以了。。。因为积得和合并一下同类项就是和的积

[HAOI2012]容易题

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#define ll long long
const int M=2100000,mod=(int)1e9+7;
int sum[M],n,m,k,cnt;
struct node{int x,y;}a[M];
bool cmp(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
int pow(int a,int k){int ans=1;for(;k;a=(1ll*a*a)%mod,k>>=1) if(k&1) ans=(1ll*ans*a)%mod;return ans;}
int main(){
    scanf("%d%d%d",&n,&m,&k);int tmp=(1ll*n*(n+1)>>1)%mod;
    for(int i=1;i<=k;i++) scanf("%d%d",&a[i].x,&a[i].y);
    std::sort(a+1,a+k+1,cmp); 
    for(int i=1;i<=k;i++){
        if(a[i].x==a[i-1].x&&a[i].y!=a[i-1].y) sum[cnt]=(sum[cnt]-a[i].y)%mod;
        else if(a[i].x!=a[i-1].x) sum[++cnt]=(tmp-a[i].y)%mod;
    }
    int ans=pow(tmp,m-cnt);
    for(int i=1;i<=cnt;i++) ans=(1ll*ans*(sum[i]+mod)%mod)%mod;
    printf("%d ",ans);
}

[HEOI2015]公约数数列
直接暴力分块
维护一个前缀gcd和亦或和。。
因为前缀gcd是递减的,且大佬说gcd不变的情况多,所以gcd改变直接暴力
不变二分。。。

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>  
#include<cstring>  
#include<cmath>
#include<algorithm>  
#include<iostream>  
#define ll long long
#define maxn 100010  
using namespace std;  
struct node  {  
    ll x;int id;  
}b[maxn];  
ll Gcd[maxn],Xor[maxn],a[maxn];  
int n,m,block,tot,L[1010],q,R[1010],t[maxn];char s[10];  
bool cmp(node x,node y)  {  
    return x.x<y.x||(x.x==y.x&&x.id<y.id);      
}  
ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}

int lower(ll x,int l,int r){
    while(l<=r){
        int mid=l+r>>1;
        if(b[mid].x>=x) r=mid-1;
        else l=mid+1;
    }
    return r+1;
}
void modify(int x){  
    Gcd[L[x]]=Xor[L[x]]=a[L[x]];b[L[x]].x=a[L[x]];b[L[x]].id=L[x];  
    for(int i=L[x]+1;i<=R[x];i++)   Gcd[i]=gcd(Gcd[i-1],a[i]),Xor[i]=Xor[i-1]^a[i],b[i].x=Xor[i],b[i].id=i;  
    sort(b+L[x],b+R[x]+1,cmp);  
}   
int query(ll x){
    ll GCD=a[0],XOR=0;
    for(int i=1;i<=tot;i++){
        if(GCD==gcd(GCD,Gcd[R[i]])){
            if(x%GCD==0){
                int tmp=lower((x/GCD)^XOR,L[i],R[i]);
                if(((b[tmp].x^XOR)*GCD)==x) return b[tmp].id;
            }
            XOR^=Xor[R[i]];
        }
        else {
            for(int j=L[i];j<=R[i];j++){
                GCD=gcd(GCD,a[j]);XOR^=a[j];
                if((GCD*XOR)==x) return j;  
            }
        }
    }
    return n;
}
int main()  {  
    scanf("%d",&n);  
    block=sqrt(n);tot=(n-1)/block+1; L[1]=0; 
    for (int i=0;i<n;i++)  {  
        t[i]=i/block+1;  
        if (!L[t[i]]&&t[i]!=1) L[t[i]]=i;  
        R[t[i]]=i;  
    }  
    for (int i=0;i<n;i++) scanf("%lld",&a[i]);  
    for (int i=1;i<=tot;i++) modify(i);  
    scanf("%d",&q);
    for(;q--;){char s[20];ll x,y;
        scanf("%s%lld",s,&x);
        if(s[0]=='M') scanf("%lld",&y),a[x]=y,modify(t[x]);
        else {int ans=0;if((ans=query(x))<n)
            printf("%d\n",ans); 
            else printf("no\n");
        }

    }

} 

[国家集训队]部落战争

这个题竟是网络流。
好像最大流就是非头结点
总结点减去非头结点就行了。。。
我也不知道为什么。。

// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;
const int M=210000;int n,m,ss,tt,inf=0x7ffffff,dg[M],r,c,A[4],B[4],id[400][400][2];char a[419][400];
struct danicliu{
    int nex[M],cos[M],to[M],head[M],tot,dep[M],cur[M];
    queue<int>q;
    void init(){
        tot=1;memset(head,0,sizeof head);
    }
    void add(int x,int y,int z){
        cos[++tot]=z;
        to[tot]=y;
        nex[tot]=head[x];
        head[x]=tot;
        cos[++tot]=0;
        to[tot]=x;
        nex[tot]=head[y];
        head[y]=tot;
    }
    int bfs(int s,int t){
        memset(dep,0,sizeof dep);
        dep[s]=1;q.push(s);
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=head[x],tmp;i;i=nex[i])
                if(!dep[tmp=to[i]]&&cos[i]) dep[tmp]=dep[x]+1,q.push(tmp);
        }
        return dep[t];
    }
    int dfs(int x,int t,int w){
        if(x==t)return w;
        for(int &i=cur[x],tmp,d;i>=2;i=nex[i]){
            if(dep[x]==dep[tmp=to[i]]-1&&cos[i]&&(d=dfs(tmp,t,min(w,cos[i])))){
                cos[i]-=d;cos[i^1]+=d;
                return d;
            }
        }
        return 0;
    }
    int danic(int s,int t){
        int flow=0,f;
        while(bfs(s,t)){
            while(1){
                for(int i=ss;i<=tt;i++) cur[i]=head[i];
                flow=flow+(f=dfs(s,t,inf));
                if(!f) break;
            }
        }
        return flow;
    }
}da;int cnt;
int main(){
    scanf("%d%d%d%d",&n,&m,&r,&c);int sum=0;ss=0,tt=2*n*m+10;da.init();
    A[1]=A[0]=r,A[2]=A[3]=c,B[1]=-c,B[0]=c,B[2]=r,B[3]=-r;
    for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)cin>>a[i][j],id[i][j][0]=++cnt,id[i][j][1]=++cnt;     
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(a[i][j]=='.') {sum++;
                da.add(ss,id[i][j][0],1),da.add(id[i][j][1],tt,1);
                for(int k=0;k<4;k++){
                    int ll=i+A[k],cc=j+B[k];
                    if(ll<1||cc<1||ll>n||cc>m||a[ll][cc]=='x')continue;
                    da.add(id[i][j][0],id[ll][cc][1],1);
                }
            }
        }

    printf("%d",sum-da.danic(ss,tt)); 
    return 0;
}


[ZJOI2009]狼和羊的故事
求最小割,把狼和羊分成两部分用的最小栅栏,就是最小割,跑最大流

// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int M=210000;int n,m,ss,tt,inf=0x7ffffff,dg[M],r[M],A[4]={0,0,-1,1},B[4]={-1,1},a[419][400],id[400][400];
struct danicliu{
    int nex[M],cos[M],to[M],head[M],tot,dep[M],cur[M];
    queue<int>q;
    void init(){
        tot=1;memset(head,0,sizeof head);
    }
    void add(int x,int y,int z){
        cos[++tot]=z;
        to[tot]=y;
        nex[tot]=head[x];
        head[x]=tot;
        cos[++tot]=0;
        to[tot]=x;
        nex[tot]=head[y];
        head[y]=tot;
    }
    int bfs(int s,int t){
        memset(dep,0,sizeof dep);
        dep[s]=1;q.push(s);
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=head[x],tmp;i;i=nex[i])
                if(!dep[tmp=to[i]]&&cos[i]) dep[tmp]=dep[x]+1,q.push(tmp);
        }
        return dep[t];
    }
    int dfs(int x,int t,int w){
        if(x==t)return w;
        for(int &i=cur[x],tmp,d;i>=2;i=nex[i]){
            if(dep[x]==dep[tmp=to[i]]-1&&cos[i]&&(d=dfs(tmp,t,min(w,cos[i])))){
                cos[i]-=d;cos[i^1]+=d;
                return d;
            }
        }
        return 0;
    }
    int danic(int s,int t){
        int flow=0,f;
        while(bfs(s,t)){
            while(1){
                for(int i=ss;i<=tt;i++) cur[i]=head[i];
                flow=flow+(f=dfs(s,t,inf));
                if(!f) break;
            }
        }
        return flow;
    }
}da;int cnt;
int main(){
    scanf("%d%d",&n,&m);ss=0,tt=n*m+1;da.init();
    for(int i=1;i<=n;i++)a[i][0]=-1,a[i][m+1]=-1;
    for(int i=1;i<=m;i++)a[0][i]=-1,a[n+1][i]=-1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]),id[i][j]=++cnt;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(a[i][j]==1)da.add(ss,id[i][j],inf);
            if(a[i][j]==2){da.add(id[i][j],tt,inf);continue;}
            for(int k=0;k<4;k++){
                int ll=i+A[k],cc=j+B[k];
                if(a[ll][cc]==-1||a[ll][cc]==1)continue;
                da.add(id[i][j],id[ll][cc],1);
            }
        }

    printf("%d",da.danic(ss,tt)); 
    return 0;
}

[AHOI2014/JSOI2014]支线剧情
上下界网络流。。。
不会,好像是建一个超源一个超汇
预先跑满一个为下届的流
再连一个为上届建下届的流

// luogu-judger-enable-o2
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int M=210000;int n,m,ss,tt,inf=0x7fffffff,dg[M],r[M];
struct danicliu{
    int nex[M],cos[M],to[M],head[M],tot,vis[M],dis[M],flow[M],cap[M],id[M],pre[M],mflow,mcost;
    queue<int>q;
    void init(){
        tot=1;memset(head,0,sizeof head);mflow=mcost=0;
    }
    void add(int x,int y,int z,int w){
        cos[++tot]=w;
        cap[tot]=z;
        to[tot]=y;
        nex[tot]=head[x];
        head[x]=tot;
        cos[++tot]=-w;
        cap[tot]=0;
        to[tot]=x;
        nex[tot]=head[y];
        head[y]=tot;
    }
    int bfs(int s,int t){

        memset(vis,0,sizeof vis);
        memset(pre,-1,sizeof pre);
        for(int i=1;i<=tt;i++) dis[i]=inf;
        dis[s]=0;q.push(s);vis[s]=1;flow[s]=inf;
        while(!q.empty()){
            int x=q.front();q.pop();vis[x]=0;
            for(int i=head[x],tmp;i>=2;i=nex[i]){
                if(dis[tmp=to[i]]>dis[x]+cos[i]&&cap[i]) {
                    dis[tmp]=dis[x]+cos[i];id[tmp]=i;
                    pre[tmp]=x;flow[tmp]=min(flow[x],cap[i]);
                    if(!vis[tmp]) vis[tmp]=1,q.push(tmp);
                }
            }       
        }
        return dis[t]<inf;
    }
    void maxflow(int s,int t){

        while(bfs(s,t)){
            int k=t;
            while(k!=s){
                cap[id[k]]-=flow[t];
                cap[id[k]^1]+=flow[t];
                k=pre[k];
            }
            mflow+=flow[t];
            mcost+=flow[t]*dis[t];
        }
    }
}da;
int main(){
    scanf("%d",&n);ss=n+1,tt=n+2;da.init();
    for(int i=1,out;i<=n;i++){
        scanf("%d",&out);
        for(int j=1,v,w;j<=out;j++){
            scanf("%d%d",&v,&w);dg[v]+=w;r[v]++;
            da.add(i,v,inf,w);
            //da.add(ss,v,1,w);
        }
        da.add(i,tt,out,0);
        if(i!=1)da.add(i,1,inf,0);
    }for(int i=1;i<=n;i++){
        if(dg[i]){
            da.add(ss,i,1,dg[i]);
            if(r[i]>1) da.add(ss,i,r[i]-1,0);
        }
    }
    da.maxflow(ss,tt);
    printf("%d",da.mcost); 
    return 0;
}

[HEOI2015]兔子与樱花
暴力贪心
把最小儿子给爸爸

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
const int M=2100000; 
int n,m,c[M],l[M],r[M],to[M],ans;
bool cmp(int a,int b){return c[a]<c[b];}
void dfs(int x){
    for(int i=l[x];i<=r[x];i++) dfs(to[i]);
    std::sort(to+l[x],to+r[x]+1,cmp);
    for(int i=l[x];i<=r[x];i++)
    if(c[to[i]]+c[x]-1<=m) ans++,c[x]+=c[to[i]]-1;
    else return ;
} 
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    for(int i=1,t,cnt=0;i<=n;i++) {
        scanf("%d",&t);l[i]=cnt+1,r[i]=cnt+t;c[i]+=t;cnt=r[i];
        for(int j=l[i];j<=r[i];j++) scanf("%d",&to[j]),to[j]++;  
    }dfs(1);
    printf("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值