【Forgiveness】(bitset优化dp) + 【new year】(maxflow+augment)

本文深入探讨了BITSET位运算优化技巧及其在高效处理字符串匹配问题的应用,同时详细解析了Maxflow增广路径算法在解决最大匹配问题中的实现细节。通过具体代码实例,展示了如何利用位运算提升算法效率,以及如何设计并实现复杂网络流问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 



这个题不知道欠了有多久....到现在还没写....

应该是又一个slot 


upd:补完了


先贴一个std

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
void Rd(int &res){
    res=0;static char p;
    while(p=getchar(),p<'0');
    do{
        res=(res*10)+(p^48);
    }while(p=getchar(),p>='0');
}
void Ps(int x){
    static int stk[64],sz;sz=0;
    while(x)stk[sz++]=x%10,x/=10;
    if(sz==0)putchar('0');
    else while(sz--)putchar(stk[sz]^48);
    putchar('\n');
}
const unsigned long long mx=-1;
const int M=50005;
unsigned long long bin[64],sbin[64];
int pcnt[(1<<16)];
int cntp(unsigned long long a){
    return pcnt[a&65535]+pcnt[(a>>16)&65535]+pcnt[(a>>32)&65535]+pcnt[(a>>48)&65535];
}
struct BITSET{
    unsigned long long val[788];
    int n,sz;
    void reset1(int n_,int ned){
        n=n_,sz=n_>>6;
        int up=ned>>6;
        for(int i=0;i<up;i++)val[i]=mx;
        val[up]=sbin[ned&63];
        for(int i=up+1;i<=sz;i++)val[i]=0;
    }
    void reset0(int n_){
        n=n_,sz=n_>>6;
        for(int i=0;i<=sz;i++)val[i]=0;
    }
    void operator &=(const BITSET &a){
        for(int i=0;i<=sz;i++)val[i]&=a.val[i];
    }
    void operator |=(const BITSET &a){
        for(int i=0;i<=sz;i++)val[i]|=a.val[i];
    }
    void operator ^=(const BITSET &a){
        for(int i=0;i<=sz;i++)val[i]^=a.val[i];
    }
    void And(const BITSET &a,BITSET &b)const{
        b.n=n,b.sz=sz;
        for(int i=0;i<=sz;i++)b.val[i]=val[i]&a.val[i];
    }
    void Or(const BITSET &a,BITSET &b)const{
        b.n=n,b.sz=sz;
        for(int i=0;i<=sz;i++)b.val[i]=val[i]|a.val[i];
    }
    void Xor(const BITSET &a,BITSET &b)const{
        b.n=n,b.sz=sz;
        for(int i=0;i<=sz;i++)b.val[i]=val[i]^a.val[i];
    }
    void shf(){
        for(int i=sz;i>0;i--)val[i]=val[i]<<1|(val[i-1]>>63);
        val[0]<<=1;
    }
    int CNT(){
        int re=0;
        for(int i=0;i<=sz;i++)re+=cntp(val[i]);
        return re;
    }
    void set(int x){
        val[x>>6]|=bin[x&63];
    }
}g[15],h[15],msk,ll,rr,f0,f1,f2,f3;
int n,m;
char S[M];
void get_msk(int l,int r){
    if(l)ll.reset1(n,l-1);
    else ll.reset0(n);
    rr.reset1(n,r);
    ll.Xor(rr,msk);
}
void solve(){
    Rd(n),Rd(m);
    scanf("%s",S+1);
    for(int i=0;i<=9;i++)g[i].reset0(n);
    for(int i=1;i<=n;i++)g[S[i]-'0'].set(i);
    for(int i=1,l,r,len,v;i<=m;i++){
        static char A[M];
        scanf("%s",A);
        if(A[0]=='?'){
            Rd(l),Rd(r),scanf("%s",A+1),len=strlen(A+1);
            if(r-l+1<len){
                puts("0");
                continue;
            }
            if(len<=3){
                Ps(r-l+1-len+1);
                continue;
            }
            get_msk(l-1,r-len);
            f0=msk;
            f1.reset0(n),f2.reset0(n),f3.reset0(n);
            for(int j=1;j<=len;j++){
                f0.shf(),f1.shf(),f2.shf(),f3.shf();
                f3&=g[A[j]-'0'],f3|=f2;
                f2&=g[A[j]-'0'],f2|=f1;
                f1&=g[A[j]-'0'],f1|=f0;
                f0&=g[A[j]-'0'];
            }
            Ps(f3.CNT());
        }else {
            Rd(l),Rd(r),Rd(v);
            get_msk(l,r);
            for(int j=0;j<=9;j++)g[j].And(msk,h[j]),g[j]^=h[j];
            for(int j=0;j<=9;j++)g[(j+v)%10]|=h[j];
        }
    }
}
int main(){
    for(int i=0;i<64;i++)bin[i]=(1uLL<<i);
    sbin[0]=1;
    for(int i=1;i<64;i++)sbin[i]=sbin[i-1]|bin[i];
    for(int i=1;i<65536;i++)pcnt[i]=pcnt[i>>1]+(i&1);
    int cas;Rd(cas);
    while(cas--)solve();
    return 0;
}

PS:感谢高铁。zx学长也说高铁上写代码甚至可以比平常效果更好!


【maxflow+augment】 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdlib>
#define N 101010
#define mo 200000
#define inf 1000000000
using namespace std;
int ans,edgenum,n,m,K,du[N],h[220],col=0,tot,jl[220][220];
int vet[N],head[220],jie[N],q[N*2],ajl[220][220];
int pri[N],vis[N],match[N],S,T,ee[220][220];
int mat[220][220],aa[N],color[300][300];
int cmp(int a,int b){
    return du[a]<du[b];
}
struct node {int id,c;}a[N];
void add(int u,int v,int w)
{
    edgenum++;vet[edgenum]=v;jie[edgenum]=head[u];head[u]=edgenum;pri[edgenum]=w;
    edgenum++;vet[edgenum]=u;jie[edgenum]=head[v];head[v]=edgenum;pri[edgenum]=0;
}
void addnew(int u,int v){
   printf("===%d %d\n",u,v);
    edgenum++;vet[edgenum]=v;jie[edgenum]=head[u];head[u]=edgenum;
}
int dfs(int u,int aug)
{
    if(u==T)return aug;
    int used=0,w,e=head[u],ee;
    while(e>0)
    {
        int v=vet[e];
        if(h[v]==h[u]+1)
        if(pri[e]>0)
        {
            if(e%2==1)ee=e+1;else ee=e-1;
            w=dfs(v,min(aug-used,pri[e]));
            used+=w;pri[e]-=w;pri[ee]+=w;
            if(used==aug)return used;
        }
        e=jie[e];
    }
    if(used<=0)h[u]=-1;return used;
}
bool bfs()
{
    for(int i=0;i<=T;i++)h[i]=-1;
    int tou=1,tail=1;q[1]=S;h[S]=0;
    while(tou<=tail)
    {
        int u=q[tou%200000],e=head[u];
        while(e>0)
        {
            int v=vet[e];
            if(h[v]<0)if(pri[e]>0)
            {
                h[v]=h[u]+1;tail++;q[tail%200000]=v;
            }
            e=jie[e];
        }
        tou++;
    }
    return (h[T]!=-1);
}
int dinic()
{
    int sum=0;
    while(bfs())
    {
        sum+=dfs(S,inf);
    }
    return sum;
}
int line(int u){
    int e=head[u];
    while(e>0){
        int i=vet[e];
        if(jl[u][i] && vis[i]==0){
            vis[i]=1;
            if(match[i]==0 || line(match[i])){
                match[u]=i;
                match[i]=u;
                return 1;
            }
        }
        e=jie[e];
    }
    return 0;
}
int maxmatch(){
    int sum=0;
    memset(match,0,sizeof(match));
    for(int i=1;i<=n/2;i++){
        if(match[i]==0){
            memset(vis,0,sizeof(vis));
            sum+=line(i);
        }
    }
    return sum;
}
void augment(int v, int c1, int c2) {
  if (color[v][c1] == 0){
    color[v][c2] = 0;
    return;
  }
  else {
    int w = color[v][c1];
    augment(w, c2, c1);
    color[v][c2] = w;
    color[w][c2] = v;
  }
}
pair<int,int> find(int a,int b){
    int af = 0, bf = 0;
  for (int c = 1; c <= K; c++) {
    if (color[a][c] == 0 && color[b][c] == 0) {
      return make_pair(c, c);
    }
    if (color[a][c] == 0) af = c;
    if (color[b][c] == 0) bf = c;
  }
  return make_pair(af, bf);
}
int main(){
    scanf("%d%d%d",&n,&m,&K);
    T=n+1;
    for(int i=1;i<=n/2;i++)add(S,i,K);
    for(int i=n/2+1;i<=n;i++)add(i,T,K);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v,1);
        ee[v][u]=edgenum;
        ajl[u][v]=i;
    }
    ans=dinic();
    printf("%d\n",ans);
    edgenum=0;
    memset(head,0,sizeof(head));
    for(int i=1;i<=n/2;i++){
        for(int j=n/2+1;j<=n;j++)if(pri[ee[j][i]]){
            pair<int,int> f=find(i,j);
            if(f.first==f.second){
                color[i][f.first]=j;
                color[j][f.first]=i;
            }else{
                augment(i,f.second,f.first);
                color[i][f.second]=j;
                color[j][f.second]=i;
            }
        }
    }
    for(int i=1;i<=n/2;i++){
        for(int j=1;j<=K;j++)if(color[i][j]>0){
            printf("%d %d\n",ajl[i][color[i][j]],j);
        }
    }
    return 0;
}

/*
8 9 2
1 6
1 7
2 7
2 8
3 5
3 8
4 5
4 6
4 8
 8 7 2
 2 6
 3 7
 4 8 
 1 6
 2 7
 3 8
 4 7
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值