zoukankan      html  css  js  c++  java
  • [loj519]数学上来先打表

    建立操作树,即1和3操作时i-1向i连边,2操作中k向i连边,然后dfs一遍

    那么当我们走到一个节点,就执行该操作(修改也是操作),退出后取消该操作即可

    于是相当于要维护一个东西,支持:1.加边;2.删边;3.询问联通块的第k小

    容易想到按秩合并并查集,考虑询问操作:用分块,维护每一个权值块的权值数量(要离散)

    然后就可以确定答案所在权值块,再依次枚举里面的权值并判断是否在联通块内即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define K 1000
     5 #define bl(k) ((k-1)/K)
     6 struct ji{
     7     int nex,to;
     8 }edge[N];
     9 vector<int>v[N];
    10 int E,n,m,p[N],a[N],x[N],y[N],b[N],head[N],sz[N],fa[N],ans[N],f[N][105];
    11 bool cmp(int x,int y){
    12     return a[x]<a[y];
    13 }
    14 void add(int x,int y){
    15     edge[E].nex=head[x];
    16     edge[E].to=y;
    17     head[x]=E++;
    18 }
    19 int find(int k){
    20     if (k==fa[k])return k;
    21     return find(fa[k]);
    22 }
    23 int query(int k){
    24     x[k]=find(x[k]);
    25     for(int i=0;i<=bl(n);i++)
    26         if (y[k]>f[x[k]][i])y[k]-=f[x[k]][i];
    27         else
    28             for(int j=i*K+1;j<=(i+1)*K;j++)
    29                 if ((find(b[j])==x[k])&&(--y[k]==0))return a[b[j]];
    30     return -1;
    31 }
    32 void add(int k){
    33     x[k]=find(x[k]);
    34     y[k]=find(y[k]);
    35     if (x[k]==y[k])return;
    36     if (sz[x[k]]>sz[y[k]])swap(x[k],y[k]);
    37     fa[x[k]]=y[k];
    38     sz[y[k]]+=sz[x[k]];
    39     for(int i=0;i<=bl(n);i++)f[y[k]][i]+=f[x[k]][i];
    40 }
    41 void del(int k){
    42     if (x[k]==y[k])return;
    43     fa[x[k]]=x[k];
    44     sz[y[k]]-=sz[x[k]];
    45     for(int i=0;i<=bl(n);i++)f[y[k]][i]-=f[x[k]][i];
    46 }
    47 void dfs(int k){
    48     if (p[k]==1)add(k);
    49     if (p[k]==3)ans[k]=query(k);
    50     for(int i=head[k];i!=-1;i=edge[i].nex)dfs(edge[i].to);
    51     if (p[k]==1)del(k);
    52 }
    53 int main(){
    54     scanf("%d%d",&n,&m);
    55     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    56     memset(head,-1,sizeof(head));
    57     for(int i=1;i<=n;i++)fa[i]=b[i]=i;
    58     sort(b+1,b+n+1,cmp);
    59     for(int i=1;i<=n;i++)sz[i]=f[b[i]][bl(i)]=1;
    60     for(int i=1;i<=m;i++){
    61         scanf("%d%d",&p[i],&x[i]);
    62         if (p[i]==2)add(x[i],i);
    63         else{
    64             scanf("%d",&y[i]);
    65             add(i-1,i);
    66         }
    67     }
    68     dfs(0);
    69     for(int i=1;i<=m;i++)
    70         if (p[i]==3)printf("%d\n",ans[i]);
    71 }
    View Code
  • 相关阅读:
    AD域新建用户
    Windows程序设计(1)
    C++ 进阶 模板和STL
    C++ 基于多态的职工管理系统
    C++核心编程
    C++入门-控制台版的通讯录管理系统
    第一章、熟悉工作环境和相关工具
    Spring整合JDBC temple
    SpringMVC整合mybaitis
    实验12 添加0号中断处理程序
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11453842.html
Copyright © 2011-2022 走看看