zoukankan      html  css  js  c++  java
  • loj558&loj2011

    loj 2011

    题意:一棵树 有两种操作 1.选定一个点 且这个点的权值随着时间的增加而增加1

                 2.查询一条路径上点的个数和权值大于C的个数

    题解:刚开始没想到离线的做法 认为可以大力线段树 n(logn)^3 然而显然过不去 被韦神教育后也考虑过树上莫队的写法 然而n^(5/3)然并卵 偷偷瞄了一眼题解

    发现我们可以这样离线一下 然后少掉一个log 对于每个querty我们找到临界位置max(0,i-C-1) 这样的话 我们只要去找当临界位置的时候在这条链上的被更新的点的个数 这样的话 我们树状数组维护就ojbk了

    #include <bits/stdc++.h>
    #define ll long long
    #define s second
    #define f first
    #define pii pair<int,int>
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=2e5+10;
    using namespace std;
    vector<int>vec[MAXN];
    int son[MAXN],fa[MAXN],num[MAXN],dep[MAXN];
    int n,q;
    void dfs1(int v,int pre,int deep){
    	num[v]=1;dep[v]=deep+1;fa[v]=pre;
    	for(int i=0;i<vec[v].size();i++){
    		int u=vec[v][i];
    		if(u!=pre){
    			dfs1(u,v,deep+1);
    			num[v]+=num[u];
    			if(son[v]==-1||num[son[v]]<num[u]) son[v]=u;
    		}
    	}
    }
    int tp[MAXN],p[MAXN],fp[MAXN],cnt;
    void dfs2(int v,int td){
    	p[v]=++cnt;fp[cnt]=v;tp[v]=td;
    	if(son[v]!=-1) dfs2(son[v],td);
    	for(int i=0;i<vec[v].size();i++){
    		int u=vec[v][i];
    		if(u!=fa[v]&&u!=son[v]) dfs2(u,u);
    	}
    }
    int d[MAXN];
    int get_id(int x){
    	return x&(-x);
    }
    void add(int x){
    	for(int i=x;i<=n;i+=get_id(i)) d[i]++;
    }
    int querty(int x){
    	int ans=0;
    	for(int i=x;i>0;i-=get_id(i)) ans+=d[i];
    	return ans;
    }
    typedef struct node{
    	int u,v,id,p;
    	friend bool operator<(node aa,node bb){
    		return aa.p<bb.p;
    	}
    }node;
    int get1(int u,int v){
    	int uu=tp[u];int vv=tp[v];
    	int ans=0;
    	while(uu!=vv){
    		if(dep[uu]<dep[vv]) swap(uu,vv),swap(u,v);
    		ans+=(p[u]-p[uu]+1);
    		u=fa[uu];uu=tp[u];
    	}
    	if(dep[u]>dep[v]) swap(u,v);
    	ans+=(p[v]-p[u]+1);
    	return ans;
    }
    int get2(int u,int v){
    	int uu=tp[u];int vv=tp[v];
    	int ans=0;
    	while(uu!=vv){
    		if(dep[uu]<dep[vv]) swap(uu,vv),swap(u,v);
    		ans+=(querty(p[u])-querty(p[uu]-1));
    		u=fa[uu];uu=tp[u];
    	}
    	if(dep[u]>dep[v]) swap(u,v);
    	ans+=(querty(p[v])-querty(p[u]-1));
    	return ans;
    }
    node que[MAXN];
    bool pd[MAXN];
    pii ans1[MAXN];
    int vis[MAXN];
    int main(){
    	scanf("%d",&n);int rt;
    	int t;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&t);son[i]=-1;
    		if(t==0){
    			rt=i;continue;
    		}
    		vec[i].push_back(t);
    		vec[t].push_back(i);
    	}cnt=0;
    	int cnt1=0;
    	dfs1(rt,0,0);dfs2(rt,rt);
    	scanf("%d",&q);
    	int op,u,v,c;
    	for(int i=1;i<=q;i++){
    		scanf("%d",&op);
    		if(op==1){
    			scanf("%d%d%d",&u,&v,&c);
    			ans1[i].f=get1(u,v);
    			que[++cnt1].u=u;que[cnt1].v=v;que[cnt1].p=max(0,i-c-1);que[cnt1].id=i;
    		}
    		else{
    			scanf("%d",&u);
    			if(pd[u]) continue;
    			vis[i]=u;pd[u]=1;
    		}
    	}
    	sort(que+1,que+cnt1+1);
    	int _=1;
    	for(int i=0;i<=q;i++){
    		if(vis[i]) add(p[vis[i]]);
    		for(;_<=cnt1&&que[_].p==i;_++){
    			ans1[que[_].id].s=get2(que[_].u,que[_].v);
    		}
    	}
    //	if(_<=cnt1){
    //		for(;_<=cnt1;_++){
    //			ans1[que[_].id].s=get2(que[_].u,que[_].v);
    //		}
    //	}
    	for(int i=1;i<=q;i++)if(!vis[i]) printf("%d %d
    ",ans1[i].f,ans1[i].s);
    	return 0;
    }
    

     loj 558

     题意:有一个森林 初始时刻每个点都是白色的  现在有四种操作

        1.对于u颜色反转

        2.连接u,v

        3.断开u,v

        4.查询与u联通的所有黑点到u的距离的和

    题解:大概很巧妙的是LCT维护子树信息 然后维护LCT维护当前节点的这段链上的贡献 注意反转的时候交换就行了 (但是这个题很毒 指针版本的LCT会A掉 然而数组版本的会T 虽然数组版本的没有A掉 就当作练习了

    #include <cctype>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define pii pair<int,int>
    #define il inline
    #define f first
    #define s second
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,l,r) for(int i=l;i>=r;i--)
    #define ll long long
    #define rg register
    const int MAXN=5e5+10;
    using namespace std;
    il int read() {
    	rg int x=0,f=1;
    	rg char ch=getchar();
    	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    int ch[MAXN][2],cnt,res[MAXN],pre[MAXN],st[MAXN],tp;
    ll sum[MAXN],chsum[MAXN],ke[MAXN],rsum[MAXN],num[MAXN],chnum[MAXN],vul[MAXN],size[MAXN];
    bool rt[MAXN],key[MAXN];
    il void reverse(int r) {
    	if(!r) return ;
    	std::swap(ch[r][0],ch[r][1]);
    	std::swap(sum[r],rsum[r]);
    	res[r]^=1;
    }
    il void push(int x) {
    	if(res[x]) {
    		reverse(ch[x][0]);
    		reverse(ch[x][1]);
    		res[x]=0;
    	}
    }
    il void up(int x) {
    	if(!x) return ;
    	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    	num[x]=num[ch[x][0]]+num[ch[x][1]]+chnum[x]+key[x];
    	vul[x]=vul[ch[x][0]]+vul[ch[x][1]]+ke[x];
    	rsum[x]=rsum[ch[x][0]]+rsum[ch[x][1]]+chsum[x]+1ll*(vul[ch[x][1]]+ke[x])*(num[ch[x][0]]+chnum[x]+key[x]);
    	sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+chsum[x]+1ll*(vul[ch[x][0]]+ke[x])*(num[ch[x][1]]+chnum[x]+key[x]);
    }
    il void P(int x) {
    	rg int i;
    	st[++tp]=x;
    	for(i=x; !rt[i]; i=pre[i]) st[++tp]=pre[i];
    	for(; tp; tp--) push(st[tp]);
    }
    il void rotate(int x,int kind) {
    	rg int y=pre[x];
    	ch[y][!kind]=ch[x][kind];
    	pre[ch[x][kind]]=y;
    	if(rt[y]) rt[x]=1,rt[y]=0;
    	else ch[pre[y]][ch[pre[y]][1]==y]=x;
    	pre[x]=pre[y];
    	ch[x][kind]=y;
    	pre[y]=x;
    	up(y);
    }
    il void splay(int x) {
    	P(x);
    	while(!rt[x]) {
    		if(rt[pre[x]]) rotate(x,ch[pre[x]][0]==x);
    		else {
    			rg int y=pre[x];
    			rg int kind=ch[pre[y]][0]==y;
    			if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
    			else rotate(y,kind),rotate(x,kind);
    		}
    	}
    	up(x);
    }
    il void access(int x) {
    	rg int y=0;
    	while(x) {
    		splay(x);
    		if(ch[x][1]) {
    			rt[ch[x][1]]=1;
    			pre[ch[x][1]]=x;
    			chsum[x]+=sum[ch[x][1]];
    			chnum[x]+=num[ch[x][1]];
    		}
    		if(y) rt[y]=0,chsum[x]-=sum[y],chnum[x]-=num[y];
    		ch[x][1]=y;
    		up(x);
    		y=x;
    		x=pre[x];
    	}
    }
    il void mroot(int u) {
    	access(u);
    	splay(u);
    	reverse(u);
    }
    il void Link(int u,int v) {
    	mroot(u);
    	mroot(v);
    	pre[u]=v;
    	chnum[v]+=num[u];
    	chsum[v]+=sum[u];
    	up(v);
    }
    il void destory(int u,int v) {
    	//if(!pd(u,v)) return ;
    	mroot(u);
    	access(v);
    	splay(u);
    	pre[v]=0;rt[v]=1;
    	ch[u][1]=0;up(u);
    	//up(x);
    }
    int main() {
    	//freopen("1.in","r",stdin);
    	//freopen("2.out","w",stdout);
    	int n,m,k;
    	n=read();
    	m=read();
    	k=read();
    	cnt=0;
    	tp=0;
    	inc(i,1,n) size[++cnt]=1,rt[cnt]=1;
    	int u,v,w;
    	while(m--) {
    		u=read();
    		v=read();
    		w=read();
    		size[++cnt]=1,rt[cnt]=1;
    		ke[cnt]=vul[cnt]=w;
    		Link(u,cnt);
    		Link(v,cnt);
    	}
    	char str[5];
    	while(k--) {
    		scanf("%s",str);
    		if(str[0]=='L') {
    			u=read(),v=read(),w=read(),size[++cnt]=1,rt[cnt]=1;
    			ke[cnt]=vul[cnt]=w;
    			Link(u,cnt),Link(v,cnt);
    		} else if(str[0]=='C') {
    			u=read();
    			v=read();
    			destory(u,v);
    		} else if(str[0]=='F') u=read(),mroot(u),key[u]^=1,up(u);
    		else u=read(),mroot(u),printf("%lld
    ",sum[u]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    java.lang.NoSuchMethodError
    asm相关内容想下载(包括 jar 包)
    Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/Type
    用Navicat连接mysql报错:2003-Can't connect to MySql server on '10.100.0.109'(10039)
    The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
    The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .class files
    交通测速方式
    卡口和电子警察的区别
    Myeclipse连接Mysql数据库时报错:Error while performing database login with the pro driver:unable
    在window上安装mysql
  • 原文地址:https://www.cnblogs.com/wang9897/p/8973551.html
Copyright © 2011-2022 走看看