bzoj2588

树上主席树。听上去好像十分高大。。然而其实思路是非常清晰地。//就是在dfs的时候更新新的主席树

然后有一个办法稍微有点巧妙。就是求x,y这一条链上某一段权值的和可以转换为sum[x]+sum[y]-sum[lca(x,y)]-sum[fa(lca(x,y)]

然后因为蒟蒻打lca只会树剖然后代码就稍显的有点长了。。。

#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#include <set>
#include <stack>
#include <queue>
#include <vector>
#include<map>
#include<list>

#define pb push_back
#define lb lower_bound
#define sqr(x) (x)*(x)
#define lowbit(x) (x)&(-x)
#define Abs(x) ((x) > 0 ? (x) : (-(x)))
#define forup(i,a,b) for(int i=(a);i<=(b);i++)
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)

#define maxn 200005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

template<class T> inline
void read(T& num)
{	num = 0;
	bool f = true;
	char ch = getchar();
	while(ch < '0' || ch > '9')
	{	if(ch == '-') f = false;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9')
	{	num = num * 10 + ch - '0';
		ch = getchar();
	}
	num = f ? num: -num;
}
int out[100];
template<class T> inline
void write(T x,char ch)
{	if (x==0)
	{	putchar('0');
		putchar(ch);
		return;
	}
	if (x<0)
	{	putchar('-');
		x=-x;
	}
	int num=0;
	while (x)
	{	out[num++]=(x%10);
		x=x/10;
	}
	fordown(i,num-1,0) putchar(out[i]+'0');
	putchar(ch);
}
/*==================split line=================*/
int n,m,cnt,tot,Clock;
int num[maxn],siz[maxn],sonh[maxn],depth[maxn],top[maxn];
int sum[maxn*10],lson[maxn*10],rson[maxn*10];
int san[maxn];
int tree[maxn];
vector<int> g[maxn];
int fa[maxn];
int LCA(int x,int y);
int ask(int x,int y,int rank)
{   int a=x,b=y,c=LCA(x,y),d=fa[c];
    a=tree[a],b=tree[b],c=tree[c],d=tree[d];
    int l=1,r=cnt;
    while(l<r)
    {
        int mid=(l+r)>>1;
        int tmp=sum[lson[a]]+sum[lson[b]]-sum[lson[c]]-sum[lson[d]];
        if(tmp>=rank)r=mid,a=lson[a],b=lson[b],c=lson[c],d=lson[d];
        else rank-=tmp,l=mid+1,a=rson[a],b=rson[b],c=rson[c],d=rson[d];
    }
    return san[l];
}
void pushup(int rt)
{	sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}

int build(int l,int r)
{	int now=++tot;
	if(l==r)  return now;
	int mid=(l+r)>>1;
	lson[now]=build(l,mid);
	rson[now]=build(mid+1,r);
	return now;
}
int updata(int rt, int pos, int L, int R)
{	int now = ++tot;
	if (L == R)
	{	sum[now] = sum[rt] + 1;
		lson[now] = rson[now] = 0;
		return now;
	}
	int m = (L + R) >> 1;
	if (pos <= m)
	{	lson[now] = updata(lson[rt], pos, L, m);
		rson[now] = rson[rt];
	}
	else
	{	rson[now] = updata(rson[rt], pos, m+ 1, R);
		lson[now] = lson[rt];
	}
	pushup(now);
	return now;
}
void mark(int node,int topn) 
{	top[node]=topn;
	if (sonh[node]!=0)  mark(sonh[node],topn);

	for(int i=0; i<g[node].size(); i++)
	{	int u=g[node][i];
		if (u!=fa[node] && u!=sonh[node])
			mark(u,u);
	}
}
int LCA(int x,int y)
{	if(x==y)  return x;
	while(top[x]!=top[y])
	{	if(depth[top[x]]<depth[top[y]])
			swap(x,y);
		x=top[x];
		x=fa[x];
	}
	if(depth[x]<depth[y]) swap(x,y);
	return y;
}
int dfs(int x,int fath)
{	fa[x]=fath;
	tree[x]=updata(tree[fath],num[x],1,cnt);
	depth[x]=depth[fath]+1;
	int tmp=0;
	int cmax=0,t=0;
	for(int i=0; i<g[x].size(); i++)
	{	int u=g[x][i];
		if(u!=fath)
		{	siz[u]=dfs(u,x);
			tmp+=siz[u];
			if(cmax<siz[u])
			{	cmax=siz[u];
				t=u;
			}
		}
	}
	sonh[x]=t;
	return tmp+1;
}

int main()
{	read(n);
	read(m);
	forup(i,1,n)  {read(num[i]),san[i]=num[i];}
	sort(san+1,san+1+n);
  	 cnt=std::unique(san+1,san+n+1)-san-1;

	for(int i=1; i<=n; i++)   num[i]=std::lower_bound(san+1,san+cnt+1,num[i])-san;
	forup(i,1,n-1)
	{	int x,y;
		read(x);
		read(y);
		g[x].pb(y);
		g[y].pb(x);
	}
	depth[1]=1;
	tree[0]=build(1,cnt);
	siz[1]=dfs(1,0);
	mark(1,1);
	int last=0;
  while(m--)
	{	int x,y,rank;
		read(x),read(y),read(rank);
		x^=last;
		last=ask(x,y,rank);
		printf("%d",last);
		if (m) puts("");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值