zoukankan      html  css  js  c++  java
  • [bzoj1103][POI2007]大都市meg_dfs序_树状数组

    大都市meg bzoj-1103 POI-2007

    题目大意:给定一颗n个点的树,m次操作。将一条路的边权更改成0;查询一个点到根节点的点权和。开始的时候所有边的边权都是1。

    注释:$1le n,mle 2.5cdot 10^5$。


    想法:我们先拉出dfs序。其实严格来讲是出栈入栈序,就是每个点在序上出现两次的那个。

    开始的时候入栈时的点权是1,出栈是-1。修改就是把出栈入栈都改成0。然后用树状数组查询前缀和即可。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 250010 
    using namespace std;
    int tree[N<<1],val[N<<1],head[N],to[N<<1],nxt[N<<1],tot,cnt;
    int dic[N<<1];
    struct Node
    {
    	int x,y;
    }a[N];
    inline int lowbit(int x) {return x&(-x);}
    void fix(int x,int delta)
    {
    	for(int i=x;i<=cnt+1;i+=lowbit(i))
    	{
    		// puts("fix");
    		tree[i]+=delta;
    	}
    }
    int query(int x)
    {
    	int ans=0;
    	for(int i=x;i>=1;i-=lowbit(i))
    	{
    		// puts("query");
    		ans+=tree[i];
    	}
    	return ans;
    }
    inline void add(int x,int y)
    {
    	to[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    void dfs(int pos,int fa)
    {
    	// if(a[pos].x) puts("FUCK");
    	dic[++cnt]=pos;
    	// cnt++;
    	val[cnt]=1;
    	a[pos].x=cnt;
    	for(int i=head[pos];i;i=nxt[i])
    	{
    		if(to[i]==fa) continue;
    		dfs(to[i],pos);
    	}
    	dic[++cnt]=pos;
    	// cnt++;
    	val[cnt]=-1;
    	a[pos].y=cnt;
    }
    int main()
    {
    	int n; cin >> n ;
    	int x,y;
    	for(int i=1;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		add(x,y); add(y,x);
    	}
    	dfs(1,0);
    	val[1]=0;
    	val[cnt]=0;
    	for(int i=1;i<=cnt;i++)
    	{
    		fix(i,val[i]);
    	}
    	// printf("Gun %d
    ",cnt);
    	// for(int i=1;i<=cnt;i++)
    	// {
    	// 	printf("Shit %d
    ",dic[i]);
    	// }
    	// puts("--------------------------------------");
    	int m; cin >> m ;
    	char opt[10];
    	// for(int i=1;i<=n;i++) printf("%d %d
    ",a[i].x,a[i].y);
    	for(int i=1;i<=n+m-1;i++)
    	{
    		// printf("Fuck %d
    ",i);
    		scanf("%s",opt+1);
    		if(opt[1]=='A')
    		{
    			scanf("%d%d",&x,&y);
    			if(x>y) swap(x,y);
    			fix(a[y].x,-1);
    			fix(a[y].y,1);
    		}
    		else
    		{
    			scanf("%d",&x);
    			// printf("%d
    ",query(3));
    			printf("%d
    ",query(a[x].x));
    		}
    	}
    	return 0;
    }
    

    小结:简单题。

  • 相关阅读:
    Java并发编程:线程池的使用
    AlarmManager与PendingIntent
    ConnectivityManager与检查网络连接的使用
    IntentService的使用
    Service(Local Service)简介
    Looper、Hander、HandlerThread
    XML_PULL解析
    android AsyncTask 的使用(转载)
    android 连接网络的简单实例
    xml drawable
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9551545.html
Copyright © 2011-2022 走看看