2016-2017 ACM-ICPC CHINA-Final G.Pandaria

本文探讨了使用GCC编译器优化级别2和3的C++代码,重点讲解了一个基于区间更新的动态规划结构(DP_DS),用于解决范围查询问题。通过`uzi`结构和`T`类,作者实现了区间树(区间更新合并)的数据结构,用于高效地处理大量数据的查询。涉及的主要技术包括递归、分治和合并操作,适用于竞赛编程和算法优化场景。
摘要由CSDN通过智能技术生成

考虑Kruscal

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
struct DP_DS{
#define mid (l+r>>1)
  struct uzi{
    int cnt,pos;
    uzi *ls,*rs;
  };
  vector<uzi *>res;
  uzi * a[500005];
  uzi * new_node(){
    auto tmp=new uzi;
    res.pb(tmp);
    tmp->cnt=0;
    tmp->pos=0;
    tmp->ls=tmp->rs=NULL;
    return tmp;
  }
  void push_up(uzi *o){
    int res=0,pos;
    if(o->ls!=NULL)res=o->ls->cnt,pos=o->ls->pos;
    if(o->rs!=NULL&&o->rs->cnt>res)res=o->rs->cnt,pos=o->rs->pos;
    o->cnt=res;
    o->pos=pos;
  }
  void up(uzi * &o,int l,int r,int x){
    if(o==NULL)o=new_node();
    if(l==r){
      o->cnt=1;
      o->pos=l;
      return;
    }
    if(x<=mid)up(o->ls,l,mid,x);
    else up(o->rs,mid+1,r,x);
    push_up(o);
  }
  uzi * merge(uzi *x,uzi *y,int l,int r){
    if(x==NULL)return y;
    if(y==NULL)return x;
    if(l==r){
      x->cnt=x->cnt+y->cnt;
      return x;
    }
    x->ls=merge(x->ls,y->ls,l,mid);
    x->rs=merge(x->rs,y->rs,mid+1,r);
    push_up(x);
    return x;
  }
  void _free(uzi *o){
    if(o->ls!=NULL)_free(o->ls);
    if(o->rs!=NULL)_free(o->rs);

    delete o;
  }
#undef mid
}T;
struct uzi{
  int x,y,val;
  bool operator < (const uzi & t)const{
    return val<t.val;
  }
}p[N];
int t,n,m,q,a[N],f[N];
int find(int x){
  return f[x]==x?x:(f[x]=find(f[x]));
}
int MX=1e6,son[N][2],cnt,val[N],dep[N],fa[N][20],ans[N];
void dfs(int now,int pa){
  dep[now]=dep[pa]+1;
  fa[now][0]=pa;
  for(int i=1;i<20;i++)fa[now][i]=fa[fa[now][i-1]][i-1];
  if(now<=n){
    ans[now]=a[now];
    return;
  }
  dfs(son[now][0],now);
  dfs(son[now][1],now);
  T.a[now]=T.merge(T.a[son[now][0]],T.a[son[now][1]],1,MX);
  ans[now]=T.a[now]->pos;
}
int CASE;
int main() {
  for(scanf("%d",&t);t;t--){
    scanf("%d%d",&n,&m);cnt=n;
    for(int i=1;i<=n;i++){
      scanf("%d", a + i);
      T.a[i]=T.new_node();
      T.up(T.a[i],1,MX,a[i]);
      f[i]=i;
    }
    for(int i=1;i<=m;i++)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].val);
    sort(p+1,p+1+m);
    printf("Case #%d:\n",++CASE);
    for(int i=1;i<=m;i++){
      int l=find(p[i].x),r=find(p[i].y);
      if(l==r)continue;
      ++cnt;
      val[cnt]=p[i].val;
      son[cnt][0]=l;
      son[cnt][1]=r;
      f[cnt]=cnt;
      f[l]=f[r]=cnt;
    }
    dfs(cnt,0);
    scanf("%d",&q);int last=0;
    for(int i=1;i<=q;i++){
      int x,y;
      scanf("%d%d",&x,&y);
      x^=last;
      y^=last;
      for(int j=19;j>=0;j--){
        if(fa[x][j] && val[fa[x][j]]<=y)x=fa[x][j];
      }
      printf("%d\n",last=ans[x]);
    }
    for(auto k:T.res){
      delete k;
    }
    T.res.clear();
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值