2024“钉耙编程”中国大学生算法设计超级联赛(4)

题面:

https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E9%9D%A2.pdf

题解:

https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E8%A7%A3.pdf

 

Code:

A. 超维攻坚

#include<cstdio>
const int N=15,inf=~0U>>1;
int Case,n,i,j,k,S,o;bool ok[(1<<N)+1];
struct P{
  int x,y,z;
  P(){}
  P(int _x,int _y,int _z){x=_x,y=_y,z=_z;}
  P operator-(const P&p)const{return P(x-p.x,y-p.y,z-p.z);}
  P operator*(const P&p)const{return P(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);}
  int operator^(const P&p)const{return x*p.x+y*p.y+z*p.z;}
}p[N];
inline int ptoplane(const P&a,const P&b,const P&c,const P&p){return((b-a)*(c-a))^(p-a);}
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
inline bool colinear(const P&a,const P&b,const P&p){
  P t=(a-b)*(b-p);
  return !t.x&&!t.y&&!t.z;
}
inline int sgn(int x){
  if(x>0)return 1;
  if(x<0)return -1;
  return 0;
}
//12v^4
inline bool check(const P&a,const P&b,const P&c,const P&p){
  return (((b-a)*(c-a))^((b-a)*(p-a)))>=0;
}
struct Face{
  P a,b,c;
  int sgn;
  bool inside(const P&p)const{
    return check(a,b,c,p)&&check(b,c,a,p)&&check(c,a,b,p);
  }
}f[N*N*N];
int main(){
  scanf("%d",&Case);
  while(Case--){
    scanf("%d",&n);
    for(i=0;i<n;i++)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
    for(i=1;i<1<<n;i++)ok[i]=0;
    for(S=1;S<1<<n;S++){
      if(__builtin_popcount(S)<=1){
        ok[S]=1;
        continue;
      }
      int m=0;
      bool same=1;
      for(i=0;i<n;i++)if(S>>i&1)for(j=0;j<i;j++)if(S>>j&1)for(k=0;k<j;k++)if(S>>k&1){
        if(colinear(p[i],p[j],p[k]))continue;
        int l=inf,r=-inf;
        for(o=0;o<n;o++)if(S>>o&1){
          int tmp=ptoplane(p[i],p[j],p[k],p[o]);
          umin(l,tmp);
          umax(r,tmp);
        }
        if(l<0&&r>0)continue;
        if(l||r)same=0;
        f[m].a=p[i];
        f[m].b=p[j];
        f[m].c=p[k];
        f[m].sgn=sgn(l)+sgn(r);
        m++;
      }
      int mask=S;
      if(!m){
        //colinear
        int xl=inf,xr=-inf;
        int yl=inf,yr=-inf;
        int zl=inf,zr=-inf;
        int idl=n,idr=0;
        for(i=0;i<n;i++)if(S>>i&1){
          umin(xl,p[i].x);umax(xr,p[i].x);
          umin(yl,p[i].y);umax(yr,p[i].y);
          umin(zl,p[i].z);umax(zr,p[i].z);
          umin(idl,i);umax(idr,i);
        }
        for(i=0;i<n;i++){
          if(S>>i&1)continue;
          if(!colinear(p[idl],p[idr],p[i]))continue;
          if(p[i].x<xl||p[i].x>xr)continue;
          if(p[i].y<yl||p[i].y>yr)continue;
          if(p[i].z<zl||p[i].z>zr)continue;
          mask|=1<<i;
        }
      }else if(same){
        //just a face
        for(i=0;i<n;i++){
          if(S>>i&1)continue;
          if(ptoplane(f[0].a,f[0].b,f[0].c,p[i]))continue;
          for(j=0;j<m;j++)if(f[j].inside(p[i])){
            mask|=1<<i;
            break;
          }
        }
      }else{
        for(i=0;i<n;i++){
          if(S>>i&1)continue;
          for(j=0;j<m;j++){
            int tmp=sgn(ptoplane(f[j].a,f[j].b,f[j].c,p[i]));
            if(tmp&&tmp!=f[j].sgn)break;
          }
          if(j==m)mask|=1<<i;
        }
      }
      ok[mask]=1;
    }
    int ans=0;
    for(i=1;i<1<<n;i++)if(ok[i])ans++;
    printf("%d\n",ans);
  }
}

  

B. 黑白边游戏

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
typedef unsigned int U;
typedef pair<U,U>P;
const int N=9,K=6,M=13055,CNT=305,inf=~0U>>1;
int a[CNT],b[CNT],f[CNT][M],perm[N],deg[N],d[N][N];bool g[N][N];U minS;
U two[N],w[N];P ident[N];
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
struct Info{
  int n,m,tot,id[N][N],apsp[K][K][M];
  map<U,int>T;
  U mask[M];
  vector<int>adj[M];
  void init(int _n){
    int i,j,k,o,A,B;
    n=_n;
    for(i=0;i<n;i++)for(j=0;j<i;j++)id[i][j]=id[j][i]=m++;
    dfs(0);
    for(i=1;i<=tot;i++){
      sort(adj[i].begin(),adj[i].end());
      adj[i].erase(unique(adj[i].begin(),adj[i].end()),adj[i].end());
    }
    int d[N][N];
    for(A=1;A<K;A++)for(B=1;B<K;B++)for(o=1;o<=tot;o++){
      U S=mask[o];
      for(i=0;i<n;i++)for(j=0;j<i;j++)d[i][j]=d[j][i]=(S>>id[i][j]&1)?B:A;
      for(i=0;i<n;i++)d[i][i]=0;
      for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)umin(d[i][j],d[i][k]+d[k][j]);
      int sum=0;
      for(i=0;i<n;i++)for(j=0;j<n;j++)sum+=d[i][j];
      apsp[A][B][o]=sum;
    }
  }
  void reorder(int x,int vis){
    if(x==n){
      U now=0;
      for(int i=0;i<n;i++)for(int j=0;j<i;j++)if(g[perm[i]][perm[j]])now|=1U<<id[i][j];
      if(minS>now)minS=now;
      return;
    }
    P mindeg(~0U>>1,0);
    for(int i=0;i<n;i++)if(!(vis>>i&1)&&mindeg>ident[i])mindeg=ident[i];
    for(int i=0;i<n;i++)if(!(vis>>i&1)&&mindeg==ident[i]){
      perm[x]=i;
      reorder(x+1,vis|(1<<i));
    }
  }
  U adjust(U S){
    int i,j;
    for(i=0;i<n;i++)deg[i]=0;
    for(i=0;i<n;i++)for(j=0;j<i;j++){
      g[i][j]=g[j][i]=S>>id[i][j]&1;
      if(g[i][j])deg[i]++,deg[j]++;
    }
    for(i=0;i<n;i++){
      two[i]=0;
      for(j=0;j<n;j++)if(g[i][j])two[i]+=w[deg[j]];
    }
    for(i=0;i<n;i++)ident[i]=P(deg[i],two[i]);
    minS=~0U;
    int vis=0,cnt=0;
    for(i=0;i<n;i++)if(deg[i]==0){
      vis|=1<<i;
      perm[cnt++]=i;
    }
    for(i=0;i<n;i++)if(deg[i]==n-1){
      vis|=1<<i;
      perm[cnt++]=i;
    }
    reorder(cnt,vis);
    return minS;
  }
  int dfs(U S){
    S=adjust(S);
    int&x=T[S];
    if(x)return x;
    x=++tot;
    mask[tot]=S;
    for(int i=0;i<m;i++)if(!(S>>i&1)){
      int y=dfs(S^(1U<<i));
      adj[x].emplace_back(y);
      adj[y].emplace_back(x);
    }
    return x;
  }
  void solve(int cnt){
    for(int j=1;j<=tot;j++)f[cnt+1][j]=0;
    for(int i=cnt;i;i--){
      int A=a[i],B=b[i];
      for(int j=1;j<=tot;j++){
        int cur=-inf;
        for(const auto&k:adj[j])umax(cur,apsp[A][B][k]-f[i+1][k]);
        f[i][j]=cur;
      }
    }
    printf("%d\n",f[1][1]);
  }
}info[N];
int main(){
  for(int i=0;i<N;i++)w[i]=(rand()<<15)^rand();
  for(int i=2;i<=8;i++)info[i].init(i);
  int Case;
  scanf("%d",&Case);
  while(Case--){
    int n,cnt;
    scanf("%d%d",&n,&cnt);
    for(int i=1;i<=cnt;i++)scanf("%d%d",&a[i],&b[i]);
    info[n].solve(cnt);
  }
}

  

C. 最优 K 子段

#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef pair<int,int>P;
const int N=200005;
int Case,n,k,i,j,a[N];bool vis[N],is_prime[N],OK;
int L,R,MID,ANS;
set<P>T;
inline void ins(int sum,int ptr){
  T.insert(P(sum,ptr));
}
inline bool valid(int sum,int ptr){
  for(set<P>::iterator it=T.begin();it!=T.end();it++){
    if(sum-it->first<MID)return 0;
    if(is_prime[ptr-it->second])return 1;
  }
  return 0;
}
inline bool check(){
  for(int cur=1,ptr=1;cur<=k;cur++){
    if(ptr>n)return 0;
    T.clear();
    ins(0,ptr-1);
    for(int sum=0;;ptr++){
      if(ptr>n)return 0;
      sum+=a[ptr];
      if(valid(sum,ptr)){
        ptr++;
        break;
      }
      ins(sum,ptr);
    }
  }
  return 1;
}
int main(){
  for(i=2;i<N;i++)if(!vis[i]){
    is_prime[i]=1;
    for(j=i;j<N;j+=i)vis[j]=1;
  }
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>k;
    L=R=OK=0;
    for(i=1;i<=n;i++){
      cin>>a[i];
      if(a[i]>0)R+=a[i];else L+=a[i];
    }
    while(L<=R){
      MID=(L+R)/2;
      if(check()){
        OK=1;
        ANS=MID;
        L=MID+1;
      }else R=MID-1;
    }
    if(OK)cout<<ANS<<"\n";else cout<<"impossible\n";
  }
}

  

D. 分组

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=21,M=10,LEN=(1<<M)+5;
int Case,n,m,i,ans,val[N],w[LEN],q[LEN],at[LEN];
bool fl[N][LEN],fr[N][LEN];
inline bool cmp(int x,int y){return w[x]<w[y];}
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void umax(int&a,int b){a<b?(a=b):0;}
void dfs(int x,int suml,int sumr){
  if(x==n){
    for(int i=0,ml=-1,mr=-1;i<1<<m;i++){
      int o=q[i];
      if(fl[n][o]&&w[o]>=w[o^suml]){
        umax(ml,w[o^suml]);
        if(~mr)umin(ans,w[o]-min(w[o^suml],mr));
      }
      if(fr[n][o]&&w[o]>=w[o^sumr]){
        umax(mr,w[o^sumr]);
        if(~ml)umin(ans,w[o]-min(w[o^sumr],ml));
      }
    }
    return;
  }
  int v=val[x];
  for(int i=0;i<1<<m;i++){
    fl[x+1][i]=fl[x][i]|fl[x][i^v];
    fr[x+1][i]=fr[x][i];
  }
  dfs(x+1,suml^v,sumr);
  for(int i=0;i<1<<m;i++){
    fl[x+1][i]=fl[x][i];
    fr[x+1][i]=fr[x][i]|fr[x][i^v];
  }
  dfs(x+1,suml,sumr^v);
}
int main(){
  scanf("%d",&Case);
  while(Case--){
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++)scanf("%d",&val[i]);
    for(i=0;i<1<<m;i++)scanf("%d",&w[i]),q[i]=i;
    sort(q,q+(1<<m),cmp);
    for(i=0;i<1<<m;i++)at[q[i]]=i;
    for(i=0;i<1<<m;i++)fl[1][i]=fr[1][i]=0;
    fl[1][0]=fr[1][0]=1;
    fl[1][val[0]]=1;
    ans=~0U>>1;
    dfs(1,val[0],0);
    printf("%d\n",ans);
  }
}

  

E. 多层血条

#include<cstdio>
const int N=805;
int Case,n,m,hp,dmg,i,j;char f[N];
int main(){
  scanf("%d",&Case);
  while(Case--){
    scanf("%d%d%d%d",&n,&m,&hp,&dmg);
    for(i=0;i<m;i++)f[i]=' ';
    int top=(hp-1)/m;
    int lim=(hp-1)%m;
    int col=top%5+'A';
    int nxt=(top+4)%5+'A';
    if(top)for(i=0;i<m;i++)f[i]=nxt;
    for(i=0;i<=lim;i++)f[i]=col;
    if(dmg>m)dmg=m;
    while(dmg--){
      f[lim]='.';
      lim=(lim+m-1)%m;
    }
    putchar('+');
    for(i=0;i<m;i++)putchar('-');
    puts("+");
    for(i=0;i<n;i++){
      putchar('|');
      for(j=0;j<m;j++)putchar(f[j]);
      puts("|");
    }
    putchar('+');
    for(i=0;i<m;i++)putchar('-');
    puts("+");
  }
}

  

F. 延时操控

#include<cstdio>
const int N=55,K=5,P=1000000007;
const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int Case,n,m,delay,hp,px,py,ex,ey,i,j,k,x,y,d,lim,o;
int f[2][N][N][K][K*2][K*2],g[2][N][N],ans;
bool ban[N][N];
char ch[N];
inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;}
inline bool check(int x,int y){
  if(x<1||x>n||y<1||y>n)return 0;
  return !ban[x][y];
}
int main(){
  scanf("%d",&Case);
  while(Case--){
    scanf("%d%d%d%d",&n,&m,&delay,&hp);
    for(i=1;i<=n;i++){
      scanf("%s",ch+1);
      for(j=1;j<=n;j++){
        if(ch[j]=='#')ban[i][j]=1;else ban[i][j]=0;
        if(ch[j]=='P')px=i,py=j;
        if(ch[j]=='E')ex=i,ey=j;
      }
    }
    ex-=px,ey-=py;
    for(o=0;o<2;o++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){
      lim=k-(x>0?x:-x);
      for(y=-lim;y<=lim;y++)f[o][i][j][k][x+K][y+K]=0;
    }
    for(o=0;o<2;o++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[o][i][j]=0;
    m-=delay;
    f[0][px][py][0][K][K]=1;
    o=0;
    while(m--){
      for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){
        lim=k-(x>0?x:-x);
        for(y=-lim;y<=lim;y++)f[o^1][i][j][k][x+K][y+K]=0;
      }
      for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){
        lim=k-(x>0?x:-x);
        for(y=-lim;y<=lim;y++){
          int now=f[o][i][j][k][x+K][y+K];
          if(!now)continue;
          for(d=0;d<4;d++){
            px=i+dx[d],py=j+dy[d];
            if(!check(px,py))continue;
            if(check(px+ex+x,py+ey+y))up(f[o^1][px][py][k][x+K][y+K],now);
            else if(k+1==hp)up(g[0][px][py],now);
            else up(f[o^1][px][py][k+1][x-dx[d]+K][y-dy[d]+K],now);
          }
        }
      }
      o^=1;
    }
    o=0;
    while(delay--){
      for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[o^1][i][j]=0;
      for(i=1;i<=n;i++)for(j=1;j<=n;j++){
        int now=g[o][i][j];
        if(!now)continue;
        for(d=0;d<4;d++){
          px=i+dx[d],py=j+dy[d];
          if(!check(px,py))continue;
          up(g[o^1][px][py],now);
        }
      }
      o^=1;
    }
    ans=0;
    for(i=1;i<=n;i++)for(j=1;j<=n;j++)up(ans,g[o][i][j]);
    printf("%d\n",ans);
  }
}

  

G. 序列更新

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=250005;
int Case,n,q,lim,i,k,x,a[N],b[N],c[N],cs,ct,S[N],T[N];
long long sum;
inline void fix(int&x){
  while(x<0)x+=n;
  while(x>=n)x-=n;
}
inline void gao(int x,int y){
  fix(x);
  fix(y);
  if(a[x]>=b[y])return;
  sum+=b[y]-a[x];
  a[x]=b[y];
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>q;
    sum=0;
    for(i=0;i<n;i++){
      cin>>a[i];
      sum+=a[i];
    }
    for(i=0;i<n;i++)cin>>b[i];
    for(i=0;i<n;i++)c[i]=b[i];
    sort(c,c+n);
    lim=sqrt(n);
    lim=max(lim,1);
    lim=min(lim,n);
    lim=c[n-lim];
    cs=ct=0;
    for(i=0;i<n;i++){
      if(a[i]<=lim)S[cs++]=i;
      if(b[i]>lim)T[ct++]=i;
    }
    while(q--){
      cin>>k;
      for(i=0;i<cs;){
        x=S[i];
        gao(x,x+k);
        if(a[x]>lim)swap(S[i],S[--cs]);else i++;
      }
      for(i=0;i<ct;i++){
        x=T[i];
        gao(x-k,x);
      }
      cout<<sum<<"\n";
    }
  }
}

  

H. 魔法卡牌

#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
const int N=63,inf=~0U>>1;
int Case,n,m,i,j,x,y,a[N],b[N],T[N],a_deg[N],b_deg[N];
ull a_all[N],a_ban[N],a_must[N],b_ban[N],nei[N],imp;
bool a_imp[N],can[N][N][2][2];
struct P{
  int val;ull way;
  P(){}
  P(int _val,ull _way){val=_val;way=_way;}
  void clr(){val=-inf;way=0;}
  void up(const P&b,int k=0){
    if(val>b.val+k)return;
    if(val<b.val+k){
      val=b.val+k;
      way=b.way;
      return;
    }
    way+=b.way;
  }
  void print(){printf("%d %llu\n",val,way);}
};
P dfs(ull S){
  if(!S)return P(0,1);
  int who=-1,best=inf;
  int cnt=__builtin_popcountll(S);
  if(imp&S)who=__builtin_ctzll(imp&S);
  else for(ull Q=S;Q;Q-=Q&-Q){
    int x=__builtin_ctzll(Q);
    if(__builtin_popcountll(nei[x]&S)<=2)continue;
    int a_deg=__builtin_popcountll(a_all[x]&S);
    int b_deg=__builtin_popcountll(b_ban[x]&S);
    int now=T[cnt-a_deg-1]+T[cnt-b_deg-1];
    if(now<best)who=x,best=now;
  }
  if(who<0){
    P ans(0,1);
    for(ull Q=S;Q;){
      int head=__builtin_ctzll(Q);
      Q-=Q&-Q;
      ull mask=S&nei[head];
      if(!mask){
        S^=1ULL<<head;
        ans.val+=max(a[head],b[head]);
        if(a[head]==b[head])ans.way*=2;
        continue;
      }
      if((mask&-mask)!=mask)continue;
      S^=1ULL<<head;
      static P dp[2][2];
      int x=head,o=0;
      for(int i=0;i<2;i++)dp[0][i].clr();
      dp[0][0]=P(a[x],1);
      dp[0][1]=P(b[x],1);
      while(S&nei[x]){
        int y=__builtin_ctzll(S&nei[x]);
        S^=1ULL<<y;
        for(int j=0;j<2;j++)dp[o^1][j].clr();
        for(int j=0;j<2;j++)if(dp[o][j].way){
          if(can[x][y][j][0])dp[o^1][0].up(dp[o][j],a[y]);
          if(can[x][y][j][1])dp[o^1][1].up(dp[o][j],b[y]);
        }
        o^=1;
        x=y;
      }
      P cur(-inf,0);
      for(int j=0;j<2;j++)if(dp[o][j].way)cur.up(dp[o][j]);
      if(!cur.way)return P(-inf,0);
      ans.val+=cur.val;
      ans.way*=cur.way;
      Q&=S;
    }
    while(S){
      int head=__builtin_ctzll(S);
      S^=1ULL<<head;
      static P dp[2][2][2];
      int x=head,o=0;
      for(int i=0;i<2;i++)for(int j=0;j<2;j++)dp[0][i][j].clr();
      dp[0][0][0]=P(a[x],1);
      dp[0][1][1]=P(b[x],1);
      while(S&nei[x]){
        int y=__builtin_ctzll(S&nei[x]);
        S^=1ULL<<y;
        for(int i=0;i<2;i++){
          for(int j=0;j<2;j++)dp[o^1][i][j].clr();
          for(int j=0;j<2;j++)if(dp[o][i][j].way){
            if(can[x][y][j][0])dp[o^1][i][0].up(dp[o][i][j],a[y]);
            if(can[x][y][j][1])dp[o^1][i][1].up(dp[o][i][j],b[y]);
          }
        }
        o^=1;
        x=y;
      }
      P cur(-inf,0);
      for(int i=0;i<2;i++)for(int j=0;j<2;j++)
        if(dp[o][i][j].way&&can[head][x][i][j])cur.up(dp[o][i][j]);
      if(!cur.way)return P(-inf,0);
      ans.val+=cur.val;
      ans.way*=cur.way;
    }
    return ans;
  }
  S^=1ULL<<who;
  P ans(-inf,0);
  for(int o=0;o<2;o++){
    ull nS=S,SA=0,SB=0,Q=0;
    int val=0;
    if(!o){
      if(a_imp[who])continue;
      val=a[who];
      SA^=a_must[who]&nS;
      SB^=a_ban[who]&nS;
      Q=a_all[who]&S;
    }else{
      val=b[who];
      SB^=b_ban[who]&nS;
      Q=b_ban[who]&nS;
    }
    nS^=Q;
    while(Q){
      int x=__builtin_ctzll(Q);
      if(SA>>x&1){
        val+=a[x];
        if(a_ban[x]&SA)break;
        if(a_must[x]&SB)break;
        if(a_imp[x])break;
        SA^=a_must[x]&nS;
        SB^=a_ban[x]&nS;
        Q^=a_all[x]&nS;
        nS^=a_all[x]&nS;
      }else{
        val+=b[x];
        if(b_ban[x]&SA)break;
        SB^=b_ban[x]&nS;
        Q^=b_ban[x]&nS;
        nS^=b_ban[x]&nS;
      }
      Q^=1ULL<<x;
    }
    if(Q)continue;
    P res=dfs(nS);
    ans.up(res,val);
  }
  return ans;
}
int main(){
  for(i=0;i<N;i++){
    if(i<=3)T[i]=1;
    else T[i]=max(T[i-1]+T[max(i-5,0)],max(T[i-2]+T[i-4],T[i-3]+T[i-3]));
    //printf("T[%d]=%d\n",i,T[i]);
  }
  scanf("%d",&Case);
  while(Case--){
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++){
      scanf("%d%d",&a[i],&b[i]);
      a_ban[i]=a_must[i]=b_ban[i]=0;
    }
    for(i=0;i<n;i++)for(j=0;j<n;j++)for(x=0;x<2;x++)for(y=0;y<2;y++)can[i][j][x][y]=1;
    while(m--){
      char op[9];
      scanf("%s%d%d",op,&x,&y);
      x--;y--;
      if(op[0]=='A'){
        //x -> !y
        //y -> !x
        a_ban[x]|=1ULL<<y;
        a_ban[y]|=1ULL<<x;
        can[x][y][0][0]=0;
        can[y][x][0][0]=0;
      }else{
        //x -> y
        //!y -> !x
        a_must[x]|=1ULL<<y;
        b_ban[y]|=1ULL<<x;
        can[x][y][0][1]=0;
        can[y][x][1][0]=0;
      }
    }
    imp=0;
    for(i=0;i<n;i++){
      a_imp[i]=!!(a_ban[i]&a_must[i]);
      if(a_imp[i])imp|=1ULL<<i;
      a_all[i]=a_ban[i]|a_must[i];
      nei[i]=a_all[i]|b_ban[i];
    }
    P ans=dfs((1ULL<<n)-1);
    ans.print();
  }
}

  

I. 昵称检索

#include<iostream>
#include<string>
using namespace std;
const int N=1000005,day[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int Case,n,m,i,j,x,ans,suf[N],f[N][26],vis[26];string a;
inline int godate(int*s){
  int x=m+1;
  for(int i=3;~i;i--){
    x--;
    if(x<1)return 0;
    x=f[x][s[i]];
  }
  return x;
}
inline int goname(){
  int x=0;
  for(int i=0;i<a.size();i++){
    x++;
    if(x>m)return m+1;
    x=f[x][a[i]-'a'];
  }
  return x;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>m>>a;
    for(j=0;j<10;j++)vis[j]=0;
    for(i=1;i<=m;i++){
      if(a[i-1]>='0'&&a[i-1]<='9')vis[a[i-1]-'0']=i;
      for(j=0;j<10;j++)f[i][j]=vis[j];
    }
    for(i=0;i<=m+1;i++)suf[i]=0;
    for(i=1;i<=12;i++)for(j=1;j<=day[i];j++){
      static int pool[4];
      pool[0]=i/10;
      pool[1]=i%10;
      pool[2]=j/10;
      pool[3]=j%10;
      x=godate(pool);
      if(x)suf[x]++;
    }
    for(i=m;i>1;i--)suf[i-1]+=suf[i];
    for(j=0;j<26;j++)vis[j]=m+1;
    for(i=m;i;i--){
      if(a[i-1]>='a'&&a[i-1]<='z')vis[a[i-1]-'a']=i;
      for(j=0;j<26;j++)f[i][j]=vis[j];
    }
    ans=0;
    while(n--){
      cin>>a;
      x=goname();
      if(x<m)ans+=suf[x+1];
    }
    cout<<ans<<"\n";
  }
}

  

J. 矩阵的周期

#include<cstdio>
typedef unsigned long long ull;
const int N=63,M=1200005;
int Case,n,m,o,i,j,k,at[N],w[N],lim[N],nxt[M];
bool g[N][N],h[N][N],can[N][N];
ull adj[N],sub0[(1<<20)+1],sub1[(1<<20)+1],sub2[(1<<20)+1],f[M];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int lcm(int a,int b){return a/gcd(a,b)*b;}
inline int getlim(int o,int x){
  if(!can[o][x])return 1;
  if(w[o]>1||w[x]>1||at[o]==at[x])return n;
  int ret=1;
  for(int i=0;i<n;i++)if(can[o][i]&&can[i][x])ret=lcm(ret,w[i]);
  return ret;
}
inline int getper(int x){
  int m=lim[x],i,j;
  for(nxt[1]=j=0,i=2;i<=m;nxt[i++]=j){
    while(j&&((f[j+1]^f[i])>>x&1))j=nxt[j];
    if(!((f[j+1]^f[i])>>x&1))j++;
  }
  return m-nxt[m];
}
int main(){
  scanf("%d",&Case);
  while(Case--){
    scanf("%d",&n);
    for(i=0;i<n;i++){
      char ch[N];
      scanf("%s",ch);
      adj[i]=0;
      for(j=0;j<n;j++){
        g[i][j]=ch[j]=='1';
        if(g[i][j])adj[i]|=1ULL<<j;
      }
    }
    for(i=0;i<n;i++)for(j=0;j<n;j++)can[i][j]=g[i][j]|(i==j);
    for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)can[i][j]|=can[i][k]&can[k][j];
    for(i=0;i<n;i++)w[i]=0;
    for(i=0;i<n;i++){
      if(w[i])continue;
      m=0;
      for(j=i;j<n;j++)if(can[i][j]&&can[j][i])m++;
      for(j=i;j<n;j++)if(can[i][j]&&can[j][i]){
        at[j]=i;
        w[j]=m;
      }
    }
    for(o=0;o<N;o++){
      for(i=0;i<n;i++)for(j=0;j<n;j++)h[i][j]=0;
      for(i=0;i<n;i++)for(j=0;j<n;j++)for(k=0;k<n;k++)h[i][k]|=g[i][j]&g[j][k];
      for(i=0;i<n;i++)for(j=0;j<n;j++)g[i][j]=h[i][j];
    }
    m=1<<(n<20?n:20);
    for(i=0;i<m;i++)sub0[i]=sub1[i]=sub2[i]=0;
    for(i=0;i<n;i++){
      j=i;
      if(j<20){sub0[1<<j]|=adj[i];continue;}else j-=20;
      if(j<20){sub1[1<<j]|=adj[i];continue;}else j-=20;
      sub2[1<<j]|=adj[i];
    }
    for(i=2;i<m;i++){
      j=i&-i;
      sub0[i]=sub0[i^j]|sub0[j];
      sub1[i]=sub1[i^j]|sub1[j];
      sub2[i]=sub2[i^j]|sub2[j];
    }
    for(o=0;o<n;o++){
      m=1;
      for(i=0;i<n;i++){
        lim[i]=getlim(o,i)*2;
        if(m<lim[i])m=lim[i];
      }
      ull S=0;
      for(i=0;i<n;i++)if(g[o][i])S|=1ULL<<i;
      for(i=1;i<=m;i++){
        f[i]=S;
        S=sub0[S&1048575]|sub1[S>>20&1048575]|sub2[S>>40];
      }
      for(i=0;i<n;i++)printf("%d%c",getper(i),i+1<n?' ':'\n');
    }
  }
}

  

K. 找环

#include<iostream>
using namespace std;
typedef unsigned int U;
typedef unsigned long long ull;
const int N=1005,M=2005,TOT=N*M*11,BASE=998244353,P=1000000007;
ull weight[N];
U SX=335634763,SY=873658265,SZ=192849106,SW=746126501;
inline ull xorshift128(){
  U t=SX^(SX<<11);
  SX=SY;
  SY=SZ;
  SZ=SW;
  return SW=SW^(SW>>19)^t^(t>>8);
}
inline ull myrand(){return (xorshift128()<<32)^xorshift128();}
int Case,inv[N],n,m,i,j,res,f[N][N],tot,l[TOT],r[TOT],val[TOT];ull sum[TOT];
struct E{int x,y,z;}e[M];
struct Frac{
  int u1,u2,d;
  Frac(){}
  Frac(int _u1,int _u2,int _d){u1=_u1,u2=_u2,d=_d;}
};
int ins(int x,int a,int b,int c){
  int y=++tot;
  val[y]=val[x]+1;
  sum[y]=sum[x]+weight[c];
  if(a==b)return y;
  int mid=(a+b)>>1;
  if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];
  else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
  return y;
}
inline bool smaller(int x,int y){
  if(y<0)return 1;
  if(sum[x]==sum[y])return 0;
  int a=1,b=n,mid;
  while(a<b){
    mid=(a+b)>>1;
    if(sum[r[x]]==sum[r[y]]){
      b=mid;
      x=l[x];
      y=l[y];
    }else{
      a=mid+1;
      x=r[x];
      y=r[y];
    }
  }
  return val[x]<val[y];
}
inline int compare(const Frac&A,const Frac&B){
  if(A.u1<0&&B.u1<0)return 0;
  if(A.u1<0)return 1;
  if(B.u1<0)return -1;
  int a=1,b=n,mid;
  int A1=A.u1,A2=A.u2,B1=B.u1,B2=B.u2,AD=A.d,BD=B.d;
  if((sum[A1]-sum[A2])*BD==(sum[B1]-sum[B2])*AD)return 0;
  //(A1-A2)/AD<(B1-B2)/BD
  //(A1-A2)*BD<(B1-B2)*AD
  while(a<b){
    mid=(a+b)>>1;
    if((sum[r[A1]]-sum[r[A2]])*BD==(sum[r[B1]]-sum[r[B2]])*AD){
      b=mid;
      A1=l[A1];
      A2=l[A2];
      B1=l[B1];
      B2=l[B2];
    }else{
      a=mid+1;
      A1=r[A1];
      A2=r[A2];
      B1=r[B1];
      B2=r[B2];
    }
  }
  int cross=(val[A1]-val[A2])*BD-(val[B1]-val[B2])*AD;
  if(!cross)return 0;
  return cross<0?-1:1;
}
void cal(int x,int y,int a,int b){
  if(a==b){
    res=(1LL*res*BASE+val[x]-val[y])%P;
    return;
  }
  int mid=(a+b)>>1;
  cal(r[x],r[y],mid+1,b);
  cal(l[x],l[y],a,mid);
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  for(inv[0]=inv[1]=1,i=2;i<N;i++)inv[i]=1LL*(P-P/i)*inv[P%i]%P;
  while(Case--){
    cin>>n>>m;
    for(i=1;i<=m;i++)cin>>e[i].x>>e[i].y>>e[i].z;
    for(i=1;i<=n;i++)weight[i]=myrand();
    for(i=0;i<=n+1;i++)for(j=1;j<=n;j++)f[i][j]=-1;
    for(j=1;j<=n;j++)f[0][j]=0;
    for(i=0;i<=n;i++)for(j=1;j<=m;j++){
      int x=e[j].x,y=e[j].y,z=e[j].z;
      int root=f[i][x];
      if(root<0)continue;
      int now=ins(root,1,n,z+1);
      if(smaller(now,f[i+1][y]))f[i+1][y]=now;
    }
    Frac ans=Frac(-1,-1,1);
    for(i=1;i<=n;i++){
      int fin=f[n+1][i];
      if(fin<0)continue;
      Frac me=Frac(0,0,1);
      for(j=0;j<=n;j++){
        int now=f[j][i];
        if(now<0)continue;
        Frac tmp(fin,now,n+1-j);
        if(compare(tmp,me)>0)me=tmp;
      }
      if(compare(me,ans)<0)ans=me;
    }
    if(ans.u1<0)cout<<"-1\n";
    else{
      res=0;
      cal(ans.u1,ans.u2,1,n);
      res=1LL*res*inv[ans.d]%P;
      cout<<res<<"\n";
    }
    for(i=1;i<=tot;i++)l[i]=r[i]=val[i]=sum[i]=0;
    tot=0;
  }
}

  

L. 寻找宝藏

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=300005;
int Case,n,m,i;ll bit[N];vector<int>gl[N],gr[N];
struct E{int y,w;ll pre,suf,val;}e[N];
struct Qry{int yl,yr;ll ans,ur,ru;}q[N];
inline void up(ll&a,ll b){a<b?(a=b):0;}
inline void ins(int x,ll p){for(;x<=n;x+=x&-x)up(bit[x],p);}
inline ll ask(int x){
  ll t=0;
  for((x>n)&&(x=n);x;x-=x&-x)up(t,bit[x]);
  return t;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>m;
    for(i=1;i<=n;i++){
      cin>>e[i].y>>e[i].w;
      gl[i].clear();
      gr[i].clear();
    }
    for(i=1;i<=m;i++){
      int xl,xr;
      cin>>xl>>q[i].yl>>xr>>q[i].yr;
      gl[xl].emplace_back(i);
      gr[xr].emplace_back(i);
    }
    for(i=1;i<=n;i++)bit[i]=0;
    for(i=1;i<=n;i++){
      for(const auto&j:gl[i])q[j].ur=ask(q[j].yr);
      e[i].pre=ask(e[i].y)+e[i].w;
      ins(e[i].y,e[i].pre);
      for(const auto&j:gr[i])q[j].ru=ask(q[j].yl-1);
    }
    for(i=0;i<=n;i++)bit[i]=0;
    for(i=n;i;i--){
      for(const auto&j:gr[i])q[j].ru+=ask(n+1-q[j].yl);
      e[i].suf=ask(n+1-e[i].y)+e[i].w;
      ins(n+1-e[i].y,e[i].suf);
      e[i].val=e[i].pre+e[i].suf-e[i].w;
      for(const auto&j:gl[i])q[j].ur+=ask(n+1-(q[j].yr+1));
    }
    for(i=1;i<=m;i++)q[i].ans=max(q[i].ur,q[i].ru);
    for(i=1;i<=n;i++)bit[i]=0;
    for(i=1;i<=n;i++){
      for(const auto&j:gl[i])up(q[j].ans,ask(n+1-(q[j].yr+1)));
      ins(n+1-e[i].y,e[i].val);
    }
    for(i=1;i<=n;i++)bit[i]=0;
    for(i=n;i;i--){
      for(const auto&j:gr[i])up(q[j].ans,ask(q[j].yl-1));
      ins(e[i].y,e[i].val);
    }
    for(i=1;i<=m;i++)cout<<q[i].ans<<"\n";
  }
}

  

posted @ 2024-08-04 16:45  Claris  阅读(73)  评论(0编辑  收藏  举报