社区讨论
求助,权值线段树过不了样例(下面那个是我弟弟)
P3224[HNOI2012] 永无乡参与者 2已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mi7xwl79
- 此快照首次捕获于
- 2025/11/21 05:25 4 个月前
- 此快照最后确认于
- 2025/11/21 05:25 4 个月前
求助啊
CPP#include<bits/stdc++.h>
using namespace std;
#define ls(_o) (tree[_o].lc)
#define rs(_o) (tree[_o].rc)
const int maxn=100010;
struct seg
{
int lc,rc;
int sum;
}tree[maxn<<10];
int n,m,q,tot;
int val[maxn],id[maxn],root[maxn],fa[maxn];
char op[3];
int get(int x)
{
return fa[x]==x?x:fa[x]=get(fa[x]);
}
void up(int p)
{
tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum;
}
void insert(int &p,int l,int r,int d)
{
if(!p) p=++tot;
if(l==r)
{
tree[p].sum++;
return;
}
int mid=(l+r)>>1;
if(d<=mid) insert(ls(p),l,mid,d);
else insert(rs(p),mid+1,r,d);
up(p);
}
int merge(int p,int q)
{
if(!p||!q) return p+q;
ls(p)=merge(ls(p),ls(q));
rs(p)=merge(rs(p),rs(q));
up(p);
return p;
}
int query(int p,int l,int r,int k)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(tree[ls(p)].sum>=k) return query(ls(p),l,mid,k);
else return query(rs(p),mid+1,r,k-tree[ls(p)].sum);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
}
for(int i=1;i<=n;i++)
{
fa[i]=i;
id[val[i]]=i;
}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
int p=get(u),q=get(v);
if(p!=q) fa[p]=q;
}
for(int i=1;i<=n;i++)
insert(root[get(i)],1,n,val[i]);
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%s",op);
if(op[0]=='Q')
{
int x,k;
scanf("%d%d",&x,&k);
int p=get(x);
if(tree[root[p]].sum<k)
{
printf("-1\n");
continue;
}
int t=query(root[p],1,n,k);
printf("%d\n",id[t]);
}
else
{
int x,y;
scanf("%d%d",&x,&y);
int p=get(x),q=get(y);
if(p!=q)
fa[p]=q,merge(root[p],root[q]);
}
}
return 0;
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...