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

数上的图

#include<iostream>
using namespace std;
#define ll long long
ll n,x,y;

ll cnt(ll x){
    ll res=0;
    while(x){
        if(x&1)res++;
        x>>=1;
    }
    return res;
}
ll lowbit(ll x){return x&(-x);}

int main(){
    std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
    cin>>n>>x>>y;
    if(x==y)cout<<0<<'\n';
    else if(cnt(x)==cnt(y))cout<<1<<'\n';
    else if(lowbit(x)==lowbit(y))cout<<1<<'\n';
    else {
        cout<<2<<'\n';
    }
}


}

#include<bits/stdc++.h>
using namespace std;
int main(){
    int T;
    cin>>T;
    while (T--){
        long long n;
        cin>>n;
        double ans = 3.0 * n / 2.0;
        printf("%.4lf\n", ans);
    }
    return 0;
}

#include<iostream>
using namespace std;
#include<map>
#define endl '\n'
const int N=2000010;
int n;int a[N];int b[N];int ans[N];
int mp[N];
int nmp[N];
int tr[N];
int lowbit(int x){return x&(-x);}
int query(int x){
    int res=0;
    for(int i=x;i>0;i-=lowbit(i)){
        res+=tr[i];
    }return res;
}
void add(int x,int k){
    for(int i=x;i<=n;i+=lowbit(i))tr[i]+=k;
}

int main(){
    std::ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int T;cin>>T;
    while(T--){
        cin>>n;for(int i=1;i<=n;i++)tr[i]=0;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)cin>>b[i];

        for(int i=1;i<=n;i++){
            mp[a[i]]=i;ans[a[i]]=i-1;
            nmp[i]=a[i];
        }
        for(int i=1;i<=n;i++)b[i]=mp[b[i]];
       // cout<<"b";for(int i=1;i<=n;i++)cout<<b[i]<<" ";cout<<endl;

        for(int i=1;i<=n;i++){
            //cout<<nmp[b[i]]<<" ";
            ans[nmp[b[i]]]+=i-1-query(b[i]);
            add(b[i],1);
        }//cout<<endl;

        for(int i=1;i<=n;i++){
            cout<<ans[i]<<" ";
        }cout<<'\n';
    }
}

苹果树

可以稍微积累一下,是中心修改

只对父亲和重儿子修改,给该节点加一个tag
查询时,如果查到轻儿子(当且仅当链首),本应该被修改但没有修改,那一定是以它的父亲为中心修改时,没有修改它,那我们就把之前给他父亲的tag加上。
如果查到重儿子,已经被更新
查到根节点,也是特殊的链首,它只能被其儿子修改,fa是0,tag是0,也满足轻儿子这个情况

#include<iostream>
using namespace std;
#include<vector>
const int N=100010;
int a[N];int n,m,rt,mod;
vector<int> G[N];
int fa[N];int dep[N];int siz[N];int son[N];
int top[N];int id[N];int nw[N];int cnt_id=0;int tag[N];
void dfs1(int u,int f){
    fa[u]=f;dep[u]=dep[f]+1;siz[u]=1;
    for(auto v:G[u]){
        if(v==f)continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[son[u]]<siz[v])son[u]=v;
    }
}

void dfs2(int u,int tp){
    top[u]=tp;id[u]=++cnt_id;nw[cnt_id]=a[u];
    if(!son[u])return ;

    dfs2(son[u],tp);
    for(auto v:G[u]){
        if(v==fa[u]||v==son[u])continue;
        dfs2(v,v);
    }
}


struct Tree{
    int l,r;
    int mx;
}tr[4*N];
void pushup(Tree& u,Tree& l,Tree& r){
    u.l=l.l;u.r=r.r;
    u.mx=max(l.mx,r.mx);
}void pushup(int u){pushup(tr[u],tr[u<<1],tr[u<<1|1]);}
void bui(int u,int l,int r){
    tr[u]={l,r,nw[l]};
    if(l==r)return ;
    int mid=(l+r)>>1;
    bui(u*2,l,mid);
    bui(u*2+1,mid+1,r);
    pushup(u);
}
void modify(int u,int x,int y,int k){
    if(x<=tr[u].l&&tr[u].r<=y){
       tr[u].mx+=k;
        return ;
    }
    int mid=(tr[u].l+tr[u].r)>>1;
    if(x<=mid)modify(u*2,x,y,k);
    if(y>=mid+1)modify(u*2+1,x,y,k);
    pushup(u);
}
Tree query(int u,int x,int y){
    if(x<=tr[u].l&&tr[u].r<=y)return tr[u];
    int mid=(tr[u].l+tr[u].r)>>1;
    if(y<=mid)return query(u*2,x,y);
    else if(x>=mid+1)return query(u*2+1,x,y);
    else {
        Tree res;
        Tree leftt=query(u*2,x,y);
        Tree rightt=query(u*2+1,x,y);
        pushup(res,leftt,rightt);
        return res;
    }
}

int query_path(int u,int v){
  int res=0;
  while(top[u]!=top[v]){
    if(dep[top[u]]<dep[top[v]]) swap(u,v);
    res=max(res,query(1,id[top[u]],id[u]).mx);
    res=max(res,nw[id[top[u]]]+tag[id[fa[top[u]]]]);//上面的查询中有链首
    u=fa[top[u]];
  }
  if(dep[u]<dep[v]) swap(u,v);
  res=max(res,query(1,id[v],id[u]).mx); 
  if(v==top[v])res=max(res,nw[id[v]]+tag[id[fa[v]]]);//u和v在同一条链上了,v深度小,如果有链首,就是v
                                    //  如果v==top[v],上面的查询中就有链首
  return res;
}


int main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        cin>>n>>m;cnt_id=0;
        for(int i=1;i<=n;i++){son[i]=0;G[i].clear();tag[i]=0;}
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n-1;i++){
            int u,v;cin>>u>>v;G[u].push_back(v);G[v].push_back(u);
        }
        dfs1(1,0);
        dfs2(1,1);
        bui(1,1,n);
        while(m--){
            int op;
            cin>>op;
            if(op==1){
                int x,y;cin>>x>>y;
                cout<<query_path(x,y)<<'\n';
            }else {
                int x,z;cin>>x>>z;
                if(fa[x]){modify(1,id[fa[x]],id[fa[x]],z);nw[id[fa[x]]]+=z;}//修改父亲
                if(son[x]){modify(1,id[son[x]],id[son[x]],z);nw[id[son[x]]]+=z;}//修改轻儿子
                tag[id[x]]+=z;//给x加tag
            }
        }
    }
}

子集

既然不相邻,那隔一个和隔两个都可以加入计算,爆搜1221537个状态,O(1e6*63)为什么可以接受?
空间只能说特别小??
太水了,只dfs(1)也过了

#include<iostream>
using namespace std;
#define int long long

/* 
void dabiao(int step){
    int g[100]={0};
    g[0]=0;g[1]=1;g[2]=1;
   for(int i=3;i<=50;i++){
    g[i]=g[i-3]+g[i-2];
   }
   cout<<g[50]+g[49]<<endl;
}
*/

int n;
int a[51];
int tem[64];int ans=0;
int insert(int x) {
    int res=-1;
  for (int i = 63; ~i; --i) {
    if (!(x >> i))
      continue;
    if (!tem[i]) {
      tem[i] = x;res=i;
      break;
    }
    x ^= tem[i];
  }
  return res;
}
void dfs(int step){
    if(step>=n+1){
        int res=0;
        for(int i=63;i>=0;i--)res=max(res,res^tem[i]);
        ans=max(ans,res);
        return ;
    }
    int t=insert(a[step]);
    dfs(step+2);
    dfs(step+3);
    if(t!=-1)tem[t]=0;
}

signed main(){
    std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
    cin>>n;ans=0;
    for(int i=1;i<=n;i++)
    cin>>a[i];
    
    dfs(1);
dfs(2);
cout<<ans<<'\n';
}

}
posted @ 2025-07-23 14:15  arin876  阅读(32)  评论(0)    收藏  举报