zoukankan      html  css  js  c++  java
  • 【ZJOI 2007】Hide 捉迷藏

      http://www.zybbs.org/JudgeOnline/problem.php?id=1095

      囧……搞了两天……

      本来一看题可以用树链剖分搞,无奈我还不会……然后想起神犇杨弋的《线段树》有这道题,于是乎膜拜了一下,发现这是最后留下的思考题= =!

      然后又发现cqx神牛的论文中有讲解,于是乎又膜拜了一下……(不是一下,是一天……)

      原理是很好理解的,用类似括号序列的方法,这样两个黑点间的距离就是未匹配括号的个数了,可以线性维护……但是写起来一个句子长得都越屏了,实在难调,做了一个小地方,要盯着屏幕找好久……(*_*)

      经过一天半的努力和QZ神牛的论文注释,终于AC了……

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #define MM 200001
    #define MN 200001
    #define INF 1000000
    #define head -1
    #define tail -2
    #define lch x<<1
    #define rch (x<<1)+1
    using namespace std;
    
    int color[MN],pos[MN],Sequence[MN*3],n,m,a,b,cnt,Dark;
    bool vis[MN];
    char s[10];
    struct EDGE{
    	int pnt;
    	EDGE *pre;
    	EDGE (){}
    	EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){}
    }Edge[MM*2],*SP=Edge,*edge[MM];
    
    struct SegmentTree{
    	int left,right,dist;
    	int left_plus,right_plus,left_minus,right_minus;
    }tree[MN*6];
    
    inline void addedge(int a,int b){
    	edge[a]=new(++SP)EDGE(b,edge[a]);
    	edge[b]=new(++SP)EDGE(a,edge[b]);
    }
    
    void NewNode(int x,int p){
    	tree[x].left=(Sequence[p]==head);
    	tree[x].right=(Sequence[p]==tail);
    	tree[x].dist=-INF;
    	tree[x].left_plus=tree[x].right_plus=tree[x].left_minus=tree[x].right_minus=(Sequence[p]>=0 && color[Sequence[p]]==0)?0:-INF;
    }
    
    void update(int x){
    	tree[x].left=tree[rch].left+max(tree[lch].left-tree[rch].right,0);
    	tree[x].right=tree[lch].right+max(tree[rch].right-tree[lch].left,0);
    	tree[x].dist=max(max(tree[lch].dist,tree[rch].dist),max(tree[lch].right_plus+tree[rch].left_minus,tree[lch].right_minus+tree[rch].left_plus));
    	tree[x].left_plus=max(tree[lch].left_plus,max(tree[rch].left_plus+tree[lch].right-tree[lch].left,tree[rch].left_minus+tree[lch].right+tree[lch].left));
    	tree[x].left_minus=max(tree[lch].left_minus,tree[rch].left_minus-tree[lch].right+tree[lch].left);
    	tree[x].right_plus=max(tree[rch].right_plus,max(tree[lch].right_plus-tree[rch].right+tree[rch].left,tree[lch].right_minus+tree[rch].right+tree[rch].left));
    	tree[x].right_minus=max(tree[rch].right_minus,tree[lch].right_minus+tree[rch].right-tree[rch].left);
    }
    	
    void build(int x,int l,int r){
    	if(l==r) NewNode(x,l);
    	else{
    		int mid=(l+r)>>1;
    		build(lch,l,mid);
    		build(rch,mid+1,r);
    		update(x);
    	}
    }
    
    void Modify(int x,int l,int r,int p){
    	if(l==r) NewNode(x,p);
    	else{
    		int mid=(l+r)>>1;
    		if(p<=mid) Modify(lch,l,mid,p);
    		else Modify(rch,mid+1,r,p);
    		update(x);
    	}
    }
    
    void dfs(int x){
    	vis[x]=true;
    	Sequence[++cnt]=head;
    	pos[x]=++cnt;
    	Sequence[cnt]=x;
    	for(EDGE *j=edge[x];j;j=j->pre)
    		if(!vis[j->pnt]) dfs(j->pnt);
    	Sequence[++cnt]=tail;
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		scanf("%d%d",&a,&b);
    		addedge(a,b);
    	}
    	int Dark=n;
    	dfs(1);
    	build(1,1,cnt);
    	scanf("%d",&m);
    	while(m--){
    		scanf("%s",s);
    		if(s[0]=='G'){
    			if(Dark==0) printf("-1\n");
    			else if(Dark==1) printf("1\n");
    			else printf("%d\n",tree[1].dist);
    		}else{
    			scanf("%d\n",&a);
    			color[a]=!color[a];
    			if(color[a]) Dark--;
    			else Dark++;
    			Modify(1,1,cnt,pos[a]);
    		}
    	}
    	return 0;
    }
    

      

      

  • 相关阅读:
    diff
    tar
    ln
    setfacl
    组件建站
    容器组件
    组件需求
    页面结构
    字体
    轮博图加元素动效的动效ransition
  • 原文地址:https://www.cnblogs.com/Delostik/p/2124061.html
Copyright © 2011-2022 走看看