2025“钉耙编程”中国大学生算法设计暑期联赛(7)

题面:

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

题解:

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

 

Code:

A. 矩形框选

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef pair<int,int>P;
const int N=10005,inf=1000000000;
int Case,n,s,w,h,i,x,y,z,ans,lim,at[N],st[N],en[N],val[N],mx[N],tag[N];
vector<P>f[N],g[N];
inline void up(int&a,int b){a<b?(a=b):0;}
inline void add(int l,int r,int p){
  int L=at[l],R=at[r],i,nmx;
  if(L==R){
    nmx=mx[L];
    for(i=l;i<=r;i++){
      val[i]+=p;
      up(nmx,val[i]);
    }
    mx[L]=nmx;
    up(ans,nmx+tag[L]);
    return;
  }
  nmx=mx[L];
  for(i=l;i<=en[L];i++){
    val[i]+=p;
    up(nmx,val[i]);
  }
  mx[L]=nmx;
  up(ans,nmx+tag[L]);
  
  nmx=mx[R];
  for(i=st[R];i<=r;i++){
    val[i]+=p;
    up(nmx,val[i]);
  }
  mx[R]=nmx;
  up(ans,nmx+tag[R]);
  
  for(i=L+1;i<R;i++){
    tag[i]+=p;
    up(ans,mx[i]+tag[i]);
  }
}
inline void del(int l,int r,int p){
  int L=at[l],R=at[r],i,nmx;
  if(L==R){
    for(i=l;i<=r;i++)val[i]-=p;
    nmx=-inf;
    for(i=st[L];i<=en[L];i++)up(nmx,val[i]);
    mx[L]=nmx;
    return;
  }
  for(i=l;i<=en[L];i++)val[i]-=p;
  nmx=-inf;
  for(i=st[L];i<=en[L];i++)up(nmx,val[i]);
  mx[L]=nmx;
  
  for(i=st[R];i<=r;i++)val[i]-=p;
  nmx=-inf;
  for(i=st[R];i<=en[R];i++)up(nmx,val[i]);
  mx[R]=nmx;
  
  for(i=L+1;i<R;i++)tag[i]-=p;
}
inline void gao(int w,int h,vector<P>f[]){
  int i;
  lim=sqrt(h);
  lim=max(lim,1);
  for(i=1;i<=n;i++){
    at[i]=(i-1)/lim;
    en[at[i]]=i;
    val[i]=0;
  }
  for(i=0;i<=at[n];i++)tag[i]=mx[i]=0;
  for(i=n;i;i--)st[at[i]]=i;
  for(i=1;i<=n;i++){
    if(i>w)
      for(const auto&it:f[i-w])
        del(it.first,min(it.first+h-1,n),it.second);
    for(const auto&it:f[i])
      add(it.first,min(it.first+h-1,n),it.second);
  }
}
inline void solve(int w,int h){
  if(w>h)gao(w,h,f);
  else gao(h,w,g);
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>s;
    for(i=1;i<=n;i++)f[i].clear(),g[i].clear();
    for(i=1;i<=n;i++){
      cin>>x>>y>>z;
      f[x].emplace_back(P(y,z));
      g[y].emplace_back(P(x,z));
    }
    ans=0;
    for(w=1;w<=n&&w<=s;w++){
      h=min(s/w,n);
      w=min(s/h,n);
      solve(w,h);
    }
    cout<<ans<<"\n";
  }
}

  

B. 龙族栖息地

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100005;
const ll inf=1LL<<60;
int Case,n;ll pool[N*2];
struct E{ll q,r,s;}e[N];
inline void umin(ll&a,ll b){a>b?(a=b):0;}
inline void umax(ll&a,ll b){a<b?(a=b):0;}
inline ll myabs(ll x){return x>0?x:-x;}
inline ll cal(ll q){
  int i;
  ll sum=0;
  for(i=1;i<=n;i++){
    pool[i]=e[i].r;
    pool[i+n]=e[i].s-q;
    sum+=myabs(e[i].q-q);
  }
  nth_element(pool+1,pool+n,pool+n*2+1);
  ll r=pool[n];
  for(i=1;i<=n*2;i++)sum+=myabs(pool[i]-r);
  return sum;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n;
    ll l=inf,r=-inf;
    ll minr=inf,maxr=-inf;
    ll mins=inf,maxs=-inf;
    for(int i=1;i<=n;i++){
      cin>>e[i].q>>e[i].r>>e[i].s;
      e[i].s*=-1;
      umin(l,e[i].q);
      umax(r,e[i].q);
      umin(minr,e[i].r);
      umax(maxr,e[i].r);
      umin(mins,e[i].s);
      umax(maxs,e[i].s);
    }
    l=min(l,mins-maxr);
    r=max(r,maxs-minr);
    ll ans=inf;
    while(l<=r){
      ll len=(r-l)/3;
      ll m1=l+len;
      ll m2=r-len;
      ll f1=cal(m1);
      ll f2=cal(m2);
      if(f1<f2){
        umin(ans,f1);
        r=m2-1;
      }else{
        umin(ans,f2);
        l=m1+1;
      }
    }
    cout<<ans/2<<"\n";
  }
}

  

C. 质疑概率

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100005;
int Case,n,k,i,a[N],b[N],sa[N],sb[N];ll v[N],q[N],lim;
inline bool checkleq(){
  if(lim>0)return 0;
  int m=1;
  q[1]=0;
  for(int i=1;i<=n;i++){
    ll x=v[i];
    if(x<lim||x>0)continue;
    if(x<=q[m]){
      q[++m]=x;
      continue;
    }
    int l=1,r=m-1,fin=m;
    while(l<=r){
      int mid=(l+r)>>1;
      if(x>q[mid])r=(fin=mid)-1;else l=mid+1;
    }
    q[fin]=x;
  }
  return m>k;
}
inline bool checkle(){
  if(lim>=0)return 0;
  int m=1;
  q[1]=0;
  for(int i=1;i<=n;i++){
    ll x=v[i];
    if(x<lim||x>=0)continue;
    if(x<q[m]){
      q[++m]=x;
      continue;
    }
    int l=1,r=m-1,fin=m;
    while(l<=r){
      int mid=(l+r)>>1;
      if(x>=q[mid])r=(fin=mid)-1;else l=mid+1;
    }
    q[fin]=x;
  }
  return m>k;
}
inline int dir(ll u,ll d){
  for(int i=1;i<=n;i++)v[i]=sb[i]*d-sa[i]*u;
  lim=v[n];
  if(checkleq()){
    if(checkle())return -1;
    return 0;
  }
  return 1;
}
inline void solve(){
  ll lu=0,ld=1,ru=1,rd=1,mu,md;
  while(1){
    mu=lu+ru;
    md=ld+rd;
    int ret=dir(mu,md);
    if(ret==0){
      cout<<mu<<"/"<<md<<"\n";
      break;
    }
    ll l=1,r,fin,mid;
    if(ret>0){//turn right
      while(1){
        r=l<<1;
        if(dir(lu+ru*r,ld+rd*r)>0)l=r;else break;
      }
      fin=l++;r--;
      while(l<=r){
        ll mid=(l+r)>>1;
        if(dir(lu+ru*mid,ld+rd*mid)>0)l=(fin=mid)+1;else r=mid-1;
      }
      lu+=ru*fin,ld+=rd*fin;
    }else{//turn left
      while(1){
        r=l<<1;
        if(dir(ru+lu*r,rd+ld*r)<0)l=r;else break;
      }
      fin=l++;r--;
      while(l<=r){
        ll mid=(l+r)>>1;
        if(dir(ru+lu*mid,rd+ld*mid)<0)l=(fin=mid)+1;else r=mid-1;
      }
      ru+=lu*fin,rd+=ld*fin;
    }
  }
}
inline bool check1(){
  static int f[N],pre[N];
  f[0]=pre[0]=0;
  for(int i=1,j=0;i<=n;i++){
    if(a[i]!=b[i])j=i;
    if(j)f[i]=pre[j-1]+1;else f[i]=-N;
    pre[i]=max(pre[i-1],f[i]);
  }
  return f[n]>=k;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>k;
    for(i=1;i<=n;i++){
      cin>>a[i]>>b[i];
      sa[i]=sa[i-1]+a[i];
      sb[i]=sb[i-1]+b[i];
    }
    if(sb[n]==0){
      cout<<"0/1\n";
      continue;
    }
    if(!check1()){
      cout<<"1/1\n";
      continue;
    }
    solve();
  }
}

  

D. 梦醒时刻

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int,int>E;
const int N=200005,M=200005,CNT=533333;
int Case,n,m,i,mx[CNT],delta[CNT];
struct P{int g,k,t,l,r,d;}bomb[N];
vector<E>e[M];
void build(int x,int a,int b){
  mx[x]=delta[x]=0;
  if(a==b)return;
  int mid=(a+b)>>1;
  build(x<<1,a,mid);
  build(x<<1|1,mid+1,b);
}
inline int ask(int x,int a,int b,int p){
  int ret=0;
  while(1){
    if(p>=mx[x])return ret;
    if(a==b)return ret+1;
    int mid=(a+b)>>1;
    if(p>=mx[x<<1]){
      a=mid+1;
      x=x<<1|1;
    }else{
      ret+=delta[x];
      b=mid;
      x<<=1;
    }
  }
}
void change(int x,int a,int b,int c,int p){
  if(a==b){
    mx[x]^=p;
    return;
  }
  int mid=(a+b)>>1;
  if(c<=mid)change(x<<1,a,mid,c,p);
  else change(x<<1|1,mid+1,b,c,p);
  mx[x]=max(mx[x<<1],mx[x<<1|1]);
  delta[x]=ask(x<<1|1,mid+1,b,mx[x<<1]);
}
inline int kth(int p,int k){
  if(ask(1,1,m,p)<k)return m+1;
  int x=1,a=1,b=m;
  while(a<b){
    int mid=(a+b)>>1;
    x<<=1;
    int tmp=ask(x,a,mid,p);
    if(k<=tmp){
      b=mid;
    }else{
      k-=tmp;
      a=mid+1;
      p=max(p,mx[x++]);
    }
  }
  return a;
}
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>>bomb[i].g>>bomb[i].k>>bomb[i].t;
      if(i<n)cin>>bomb[i].l>>bomb[i].r>>bomb[i].d;
    }
    build(1,1,m);
    for(i=1;i<=n;i++){
      for(const auto&it:e[i])change(1,1,m,it.first,it.second);
      int t=min(kth(bomb[i].g,bomb[i].k)+1,bomb[i].t);
      cout<<t;
      if(i<n){
        cout<<" ";
        e[bomb[i].l].emplace_back(E(t,bomb[i].d));
        e[bomb[i].r+1].emplace_back(E(t,bomb[i].d));
      }else cout<<"\n";
    }
    for(i=1;i<=n+1;i++)e[i].clear();
  }
}

  

E. 地图编辑器

#include<iostream>
using namespace std;
const int N=15;
int Case,n,m,k,i,j,x,y,f[N][N];char c[N][N];
inline void draw(int x,int y,int w){
  if(x<1||y<1||y>m)return;
  c[x][y]=w;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>m>>k;
    for(i=1;i<=n;i++)for(j=1;j<=m;j++){
      f[i][j]=0;
      c[i][j]='.';
    }
    for(i=1;i<=k;i++){
      cin>>x>>y;
      f[x][y]=i;
    }
    for(i=1;i<=n;i++)for(j=1;j<=m;j++){
      x=f[i][j];
      if(!x)continue;
      x+='0';
      draw(i,j,x);
      draw(i-1,j,x);
      for(k=j-2;k<=j+2;k++)draw(i-2,k,x);
      for(k=j-1;k<=j+1;k++)draw(i-3,k,x);
      draw(i-4,j,x);
    }
    for(i=1;i<=n;i++){
      for(j=1;j<=m;j++)cout<<c[i][j];
      cout<<"\n";
    }
  }
}

  

F. 伤害冷却比

#include<iostream>
using namespace std;
typedef long long ll;
int Case;
ll mygcd(ll a,ll b){return b?mygcd(b,a%b):a;}
struct Frac{
  ll u,d;
  Frac(){}
  Frac(ll _u,ll _d){u=_u,d=_d;}
  void show(){
    ll g=mygcd(u,d);
    cout<<u/g<<"/"<<d/g<<"\n";
  }
  bool operator>=(const Frac&p)const{return u*p.d>=p.u*d;}
}k,l,r;
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>k.u>>k.d>>l.u>>l.d>>r.u>>r.d;
    Frac tmp(k.u*r.d,k.d*r.u);
    ll v=tmp.u/tmp.d+1;
    Frac ans(r.u*v,r.d);
    if(tmp.u%tmp.d){
      Frac x(k.u,k.d*v);
      if(x>=l){
        Frac now(x.u*(v+1),x.d);
        if(now>=ans)ans=now;
      }
    }
    ans.show();
  }
}

  

G. 满员电车

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int,int>P;
const int N=200005,M=1111111,inf=~0U>>1;
int Case,n,m,ca,cb,q,i,x,S,T,d[N],cov[N],f[N];
int pos[N*2],mia[M],mxb[M],best[M];
P pool[N*2];
vector<int>ga[N],gb[N];
struct E{int t,l,r,p;}a[N],b[N];
void build(int x,int a,int b){
  mia[x]=inf;
  mxb[x]=-1;
  best[x]=inf;
  if(a==b){
    pos[a]=x;
    return;
  }
  int mid=(a+b)>>1;
  build(x<<1,a,mid);
  build(x<<1|1,mid+1,b);
}
inline void change(int x,int a,int b){
  x=pos[x];
  mia[x]=a;
  mxb[x]=b;
  for(x>>=1;x;x>>=1){
    mia[x]=min(mia[x<<1],mia[x<<1|1]);
    mxb[x]=max(mxb[x<<1],mxb[x<<1|1]);
    best[x]=min(best[x<<1],best[x<<1|1]);
    if(mxb[x<<1]>=0&&mia[x<<1|1]<inf)best[x]=min(best[x],mia[x<<1|1]-mxb[x<<1]);
  }
}
inline int query(int S,int T){
  if(cov[S])return d[T]-d[S];
  if(f[S]==inf)return -1;
  return f[S]-d[n]+d[S]+d[T];
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>ca>>cb>>q;
    for(i=1;i<=n;i++)cin>>d[i];
    for(i=1;i<=ca;i++){
      cin>>a[i].t>>a[i].l>>a[i].r;
      pool[i]=P(a[i].t-d[n]+2*d[a[i].r],i);
      cov[a[i].l]++;
      cov[a[i].r+1]--;
      ga[a[i].r].emplace_back(i);
    }
    for(i=1;i<=cb;i++){
      cin>>b[i].t>>b[i].l>>b[i].r;
      pool[i+ca]=P(b[i].t,-i);
      gb[b[i].l].emplace_back(i);
      gb[b[i].r+1].emplace_back(-i);
    }
    m=ca+cb;
    sort(pool+1,pool+m+1);
    for(i=1;i<=ca+cb;i++){
      x=pool[i].second;
      if(x>0)a[x].p=i;else b[-x].p=i;
    }
    build(1,1,m);
    for(i=1;i<=n;i++){
      for(const auto&it:ga[i])change(a[it].p,a[it].t,-1);
      for(const auto&it:gb[i])if(it>0)change(b[it].p,inf,b[it].t);else change(b[-it].p,inf,-1);
      cov[i]+=cov[i-1];
      f[i]=best[1];
    }
    while(q--){
      cin>>S>>T;
      cout<<query(S,T)<<"\n";
    }
    for(i=1;i<=n+1;i++){
      cov[i]=0;
      ga[i].clear();
      gb[i].clear();
    }
  }
}

  

H. 飞行训练

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=50005,K=8,BLK=(N>>K)+1;
int Case,n,m,i,j;
vector<int>g[N];
ll ans;
int rangel[N],ranger[N],pool[N*2],cb,st[BLK],en[BLK];
int at[BLK][N],cov[BLK][(1<<(K+1))+5],val[BLK][(1<<(K+1))+5],sz[BLK],sum[BLK];
struct E{int u,l,r,L,R;}e[N];
inline bool cmp(const E&a,const E&b){return a.u<b.u;}
inline void init(){
  int i,j,k,cp,_;
  for(i=1,j=0;i<=n;i++){
    while(j<m&&e[j+1].u<=i)j++;
    ranger[i]=j;
  }
  for(i=n,j=m+1;i;i--){
    while(j>1&&e[j-1].u>=i)j--;
    rangel[i]=j;
  }
  cb=m>>K;
  for(i=1;i<=m;i++)en[i>>K]=i;
  for(i=m;i;i--)st[i>>K]=i;
  pool[0]=0;
  for(i=0;i<=cb;i++){
    sum[i]=0;
    pool[cp=1]=n;
    for(j=st[i];j<=en[i];j++){
      pool[++cp]=e[j].l-1;
      pool[++cp]=e[j].r;
    }
    sort(pool,pool+cp+1);
    _=cp;
    cp=0;
    for(j=1;j<=_;j++)if(pool[j]>pool[j-1])pool[++cp]=pool[j];
    sz[i]=cp;
    for(j=0;j<=cp;j++)cov[i][j]=val[i][j]=0;
    for(j=1;j<=cp;j++)for(k=pool[j-1]+1;k<=pool[j];k++)at[i][k]=j;
    for(j=st[i];j<=en[i];j++){
      e[j].L=at[i][e[j].l];
      e[j].R=at[i][e[j].r];
      cov[i][e[j].L]++;
      cov[i][e[j].R+1]--;
    }
    for(j=1;j<=cp;j++)cov[i][j]+=cov[i][j-1];
  }
}
inline void modify(int x,int p){
  for(int i=0;i<=cb;i++){
    int y=at[i][x];
    sum[i]+=cov[i][y]*p;
    val[i][y]+=p;
  }
}
inline void ask(int o,int l,int r){
  int i,m=sz[o];
  for(i=1;i<=m;i++)pool[i]=pool[i-1]+val[o][i];
  for(i=l;i<=r;i++)ans+=pool[e[i].R]-pool[e[i].L-1];
}
inline void query(int l,int r){
  l=rangel[l],r=ranger[r];
  if(l>r)return;
  int L=l>>K,R=r>>K;
  for(int i=L+1;i<R;i++)ans+=sum[i];
  if(L==R)ask(L,l,r);
  else{
    ask(L,l,en[L]);
    ask(R,st[R],r);
  }
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>m;
    ans=0;
    for(i=1;i<=n+1;i++)g[i].clear();
    for(i=1;i<=m;i++)cin>>e[i].u>>e[i].l>>e[i].r;
    sort(e+1,e+m+1,cmp);
    for(i=1;i<=m;i++){
      g[e[i].l].emplace_back(i);
      g[e[i].r+1].emplace_back(-i);
    }
    init();
    for(i=1;i<=n;i++){
      for(const auto&it:g[i])if(it>0)modify(e[it].u,1);else modify(e[-it].u,-1);
      for(j=rangel[i];j<=ranger[i];j++)query(e[j].l,e[j].r);
    }
    cout<<ans<<"\n";
  }
}

  

I. 崭新的假日

#include<iostream>
#include<algorithm>
using namespace std;
const int days[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int Case,n,m,i,l,r,k,year,month,day,g[555],ans;
inline bool check(int year,int month,int day){
  if(month==2&&day==29&&year%4)return 0;
  if(month<3){
    year-=1;
    month+=12;
  }
  int c=year/100,y=year-100*c;
  int w=c/4-2*c+y+y/4+(26*(month+1)/10)+day-1;
  w=(w%7+7)%7;
  return w>=1&&w<=5;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>k>>l>>r;
    n=0;
    for(month=1;month<=12;month++)for(day=1;day<=days[month];day++){
      m=0;
      for(year=l;year<=r;year++)m+=check(year,month,day);
      g[++n]=m;
    }
    sort(g+1,g+n+1);
    ans=0;
    for(i=1;i<=k;i++)ans+=g[i];
    cout<<ans<<"\n";
  }
}

  

J. 情报污染

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int N=50005,M=50005,K=253,W=4,CNT=(M*2+K)*2+5,inf=~0U>>1;
int Case,n,m,cnt,A,B,C,lim,i,x,y,u,v,w,o,pre[N];
P p[N];
vector<P>cons[N];
vector<int>g[CNT],h[CNT];
bool vis[CNT];
int scc,from[CNT],t,s[CNT];
ull mask[CNT][W],reach[CNT][W];
inline void add_edge(int x,int y){
  g[x].emplace_back(y);
  h[y].emplace_back(x);
}
struct Pool{
  vector<int>v;
  int st,len;
  bool big;
  void clear(){v.clear();}
  void ext(int x){v.emplace_back(x);}
  int find(int x){
    int idx=lower_bound(v.begin(),v.end(),x)-v.begin();
    return st+idx;
  }
  int get_prev(int x){
    if(!len)return -1;
    const auto&it=lower_bound(v.begin(),v.end(),x);
    if(it==v.begin())return -1;
    int idx=it-v.begin();
    return st+idx-1;
  }
  void build(){
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    len=v.size();
    st=cnt;
    cnt+=len;
  }
  void add_adj_edges(){
    for(int i=1;i<len;i++){
      add_edge(st+i-1,st+i);
      add_edge(st+i+cnt,st+i-1+cnt);
    }
  }
  void make_pre(){
    big=len>lim;
    if(big)for(int i=0;i+1<len;i++)for(int j=v[i];j<v[i+1];j++)pre[j]=st+i;
  }
}upper[N];
struct E{
  int x,y,w;
  E(){}
  E(int _x,int _y,int _w){x=_x,y=_y,w=_w;}
}e[M],a[M],b[M],c[K];
inline int dis(const P&a,const P&b){
  ll dx=a.first-b.first,dy=a.second-b.second;
  ll tmp=dx*dx+dy*dy;
  ll ret=sqrt(tmp)-3;
  ret=max(ret,0LL);
  while(ret*ret<tmp)ret++;
  return ret;
}
inline void add_or(int x,int y){
  add_edge(x+cnt,y);
  add_edge(y+cnt,x);
}
inline void add_nand(int x,int y){
  add_edge(x,y+cnt);
  add_edge(y,x+cnt);
}
inline void add_constraints(const Pool&a,const Pool&b,int w){
  if(b.big){
    for(int i=0;i<a.len;i++){
      int r=w-a.v[i]-1;
      if(r<b.v[0])return;
      add_nand(a.st+i,r<b.v[b.len-1]?pre[r]:(b.st+b.len-1));
    }
  }else for(int i=0,j=b.len-1;i<a.len;i++){
    while(j>=0&&a.v[i]+b.v[j]>=w)j--;
    if(j<0)return;
    add_nand(a.st+i,b.st+j);
  }
}
void dfs(int x){
  vis[x]=1;
  for(const auto&y:h[x])if(!vis[y])dfs(y);
  s[++t]=x;
}
inline void go(int x){
  static int q[CNT];
  static ull now[W];
  int h=1,t=1,i;
  q[1]=x;
  vis[x]=0;
  from[x]=++scc;
  for(i=0;i<W;i++)now[i]=0;
  while(h<=t){
    x=q[h++];
    for(i=0;i<W;i++)now[i]|=mask[x][i];
    for(const auto&y:g[x])if(vis[y]){
      q[++t]=y;
      vis[y]=0;
      from[y]=scc;
    }else if(from[y]<scc){
      int z=from[y];
      now[0]|=reach[z][0];
      now[1]|=reach[z][1];
      now[2]|=reach[z][2];
      now[3]|=reach[z][3];
    }
  }
  for(i=0;i<W;i++)reach[scc][i]=now[i];
}
inline void up(int&x,int y){x>y?(x=y):0;}
inline bool check(int x,int y){return reach[from[c[x].y]][y>>6]>>(y&63)&1;}
inline int solve(){
  int i,j;
  for(i=0;i<cnt;i++)if(from[i]==from[i+cnt])return 0;
  int ans=inf;
  for(i=0;i<C;i++){
    if(check(i,i))up(ans,c[i].w);
    for(j=0;j<i;j++)if(check(i,j)&&check(j,i))up(ans,c[i].w+c[j].w);
  }
  if(ans==inf)ans=-1;
  return ans;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n>>m>>A>>B>>C;
    for(i=0;i<n;i++)cin>>p[i].first>>p[i].second;
    for(i=0;i<m;i++){
      cin>>x>>y;
      x--,y--;
      e[i]=E(x,y,dis(p[x],p[y]));
    }
    for(i=0;i<n;i++){
      upper[i].clear();
      cons[i].clear();
    }
    for(i=0;i<A;i++){
      cin>>x>>y>>w;
      x--,y--;
      a[i]=E(x,y,w);
    }
    for(i=0;i<B;i++){
      cin>>x>>y>>w;
      x--,y--;
      b[i]=E(x,y,w);
      upper[x].ext(w);
      upper[y].ext(w);
    }
    for(i=0;i<C;i++){
      cin>>x>>y>>w;
      x--;
      c[i]=E(x,y,w);
      upper[x].ext(y);
    }
    cnt=0;
    for(i=0;i<n;i++)upper[i].build();
    for(i=0;i<cnt*2;i++){
      g[i].clear();
      h[i].clear();
      for(o=0;o<W;o++)mask[i][o]=0;
    }
    for(i=0;i<A;i++){
      x=a[i].x,y=a[i].y,w=a[i].w;
      u=upper[x].get_prev(w);
      v=upper[y].get_prev(w);
      if(~u&&~v)add_nand(u,v);
    }
    for(i=0;i<B;i++){
      x=b[i].x,y=b[i].y,w=b[i].w;
      add_or(upper[x].find(w),upper[y].find(w));
    }
    for(i=0;i<C;i++){
      o=upper[c[i].x].find(c[i].y);
      c[i].x=o+cnt;
      c[i].y=o;
      mask[c[i].x][i>>6]|=1ULL<<(i&63);
    }
    for(i=0;i<n;i++)upper[i].add_adj_edges();
    for(i=0;i<m;i++){
      x=e[i].x,y=e[i].y;
      if(upper[x].len>upper[y].len)swap(x,y);
      cons[y].emplace_back(P(x,e[i].w));
    }
    lim=sqrt((2.0*B*n)/max(m,1));
    for(i=0;i<n;i++){
      if(!upper[i].len||!cons[i].size())continue;
      upper[i].make_pre();
      for(const auto&con:cons[i])add_constraints(upper[con.first],upper[i],con.second);
    }
    scc=t=0;
    for(i=0;i<cnt*2;i++)if(!vis[i])dfs(i);
    for(i=t;i;i--)if(vis[s[i]])go(s[i]);
    cout<<solve()<<"\n";
  }
}

  

K. 切披萨

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=200005;
int Case,n,m,i,j,k,qa[N],qb[N],tmp[N],fin[N];
struct P{int x,y;}a[N];
struct Line{
  int a,b;ll c;
  bool contain(const P&p)const{return 1LL*a*p.x+1LL*b*p.y<=c;}
}b[N],hull[N];
ll lim[N];
inline ll pos(const Line&p,const Line&q){
  return (p.c*q.b-q.c*p.b)/(1LL*p.a*q.b-1LL*q.a*p.b);
}
inline bool cmpa(int p,int q){return a[p].x<a[q].x;}
inline bool cmpb(int p,int q){
  ll cross=1LL*b[p].a*b[q].b-1LL*b[q].a*b[p].b;
  if(cross)return cross>0;
  return b[p].c*b[q].b>b[q].c*b[p].b;
}
inline bool cmpfin(int p,int q){return fin[p]==fin[q]?p<q:fin[p]<fin[q];}
void solve(int al,int ar,int bl,int br){
  int i,o;
  if(bl==br){
    const Line&B=b[bl];
    for(i=al;i<=ar;i++){
      o=qa[i];
      fin[o]=B.contain(a[o])?bl:m+1;
    }
    return;
  }
  int mid=(bl+br)>>1,t=0;
  for(i=bl;i<=br;i++){
    o=qb[i];
    if(o>mid)continue;
    const Line&now=b[o];
    if(t&&1LL*hull[t].a*now.b==1LL*hull[t].b*now.a)continue;
    while(t>1&&pos(hull[t],now)<=lim[t-1])t--;
    if(t)lim[t]=pos(hull[t],now);
    hull[++t]=now;
  }
  int tl=al-1,tr=ar+1,h=1;
  for(i=al;i<=ar;i++){
    o=qa[i];
    while(h<t&&a[o].x>lim[h])h++;
    if(hull[h].contain(a[o]))tmp[++tl]=o;else tmp[--tr]=o;
  }
  reverse(tmp+tr,tmp+ar+1);
  for(i=al;i<=ar;i++)qa[i]=tmp[i];
  int l=bl-1,r=mid;
  for(i=bl;i<=br;i++){
    o=qb[i];
    if(o<=mid)tmp[++l]=o;else tmp[++r]=o;
  }
  for(i=bl;i<=br;i++)qb[i]=tmp[i];
  if(al<=tl)solve(al,tl,bl,mid);
  if(tr<=ar)solve(tr,ar,mid+1,br);
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n;
    for(i=1;i<=n;i++){
      cin>>a[i].x>>a[i].y;
      qa[i]=i;
    }
    cin>>m;
    for(i=1;i<=m;i++){
      cin>>b[i].a>>b[i].b>>b[i].c;
      qb[i]=i;
    }
    sort(qa+1,qa+n+1,cmpa);
    sort(qb+1,qb+m+1,cmpb);
    solve(1,n,1,m);
    sort(qa+1,qa+n+1,cmpfin);
    for(i=j=1;i<=m;i++){
      for(k=j;k<=n&&fin[qa[k]]==i;k++);
      cout<<k-j;
      while(j<k)cout<<" "<<qa[j++];
      cout<<"\n";
    }
  }
}

  

L. 字典树逆向

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef unsigned long long ull;
const int N=200005,P=998244353,LESS=0,GREATER=1,SUB=2,CONTAIN=3,SAME=4;
int Case,n,m,i,x,deg[N];vector<int>son[N];
int compare(int x,int y){
  int n=deg[x],m=deg[y],i=0;
  if(!n&&!m)return SAME;
  if(!n)return LESS;
  if(!m)return GREATER;
  while(i<n&&i<m){
    int t=compare(son[x][i],son[y][i]);
    if(t==SAME){
      i++;
      continue;
    }
    if(t==SUB&&i+1<n)return GREATER;
    if(t==CONTAIN&&i+1<m)return LESS;
    return t;
  }
  if(i==n&&i==m)return SAME;
  return i==n?SUB:CONTAIN;
}
inline bool cmp(int x,int y){
  if(x==y)return 0;
  int t=compare(x,y);
  return t==LESS||t==CONTAIN;
}
void dfs(int x,ull h){
  if(!deg[x]){
    cout<<h<<"\n";
  }
  h*=P;
  for(int i=0;i<deg[x];i++)dfs(son[x][i],h+i+1);
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>Case;
  while(Case--){
    cin>>n;
    for(i=1;i<=n;i++)son[i].clear();
    for(i=2;i<=n;i++){
      cin>>x;
      son[x].emplace_back(i);
    }
    for(m=0,i=n;i;i--){
      deg[i]=son[i].size();
      if(deg[i]==0)m++;else sort(son[i].begin(),son[i].end(),cmp);
    }
    cout<<m<<"\n";
    dfs(1,0);
  }
}

  

posted @ 2025-08-10 17:32  Claris  阅读(47)  评论(0)    收藏  举报