zoukankan      html  css  js  c++  java
  • zoj3686(线段树的区间更新)

    对线段树的区间更新有了初步的了解。。。

    A Simple Tree Problem

    Time Limit: 3 Seconds      Memory Limit: 65536 KB

    Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.

    We define this kind of operation: given a subtree, negate all its labels.

    And we want to query the numbers of 1's of a subtree.

    Input

    Multiple test cases.

    First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)

    Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.

    Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.

    Output

    For each query, output an integer in a line.

    Output a blank line after each test case.

    Sample Input

    3 2
    1 1
    o 2
    q 1
    

    Sample Output

    1
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    #include <map>
    #include <queue>
    #include <sstream>
    #include <iostream>
    using namespace std;
    #define INF 0x3fffffff
    #define N 100100
    
    int n,m;
    struct node
    {
        int to,next;
    }edge[2*N];
    
    struct node1
    {
        int b,d,mid;
        int flag,sum;
    }tnode[3*N];
    
    int cnt,pre[N];
    int savex[N],savey[N];
    int id;
    
    // 线段树的区间更新初步了解!
    
    void add_edge(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=pre[u];
        pre[u]=cnt++;
    }
    
    void dfs(int s,int path)
    {
        int tmp;
        ++id;
        tmp=id;
        for(int p=pre[s];p!=-1;p=edge[p].next)
        {
            int v=edge[p].to;
            if(v!=path)
            {
                dfs(v,s);
            }
        }
        savex[s]=tmp;
        savey[s]=id;
    }
    
    
    void built(int b,int d,int s)
    {
        tnode[s].b=b;
        tnode[s].d=d;
        tnode[s].mid=(b+d)/2;
        tnode[s].sum=0;
        tnode[s].flag=0;
        if(b==d) return ;
        built(b,tnode[s].mid,2*s);
        built(tnode[s].mid+1,d,2*s+1);
    }
    
    void insert(int b,int d,int s)
    {
        if(tnode[s].b==b&&tnode[s].d==d)
        {
            tnode[s].flag^=1;
            tnode[s].sum=(d-b+1) - tnode[s].sum;
            return ;
        }
        if(tnode[s].flag!=0)
        {
            tnode[s].flag=0;
            tnode[2*s].flag^=1;
            tnode[2*s].sum=(tnode[2*s].d-tnode[2*s].b+1)-tnode[2*s].sum;
    
            tnode[2*s+1].flag^=1;
            tnode[2*s+1].sum=(tnode[2*s+1].d-tnode[2*s+1].b+1)-tnode[2*s+1].sum;
        }
        if(tnode[s].mid>=d)
            insert(b,d,2*s);
        else if(tnode[s].mid+1<=b)
            insert(b,d,2*s+1);
        else
        {
            insert(b,tnode[s].mid,2*s);
            insert(tnode[s].mid+1,d,2*s+1);
        }
        tnode[s].sum=tnode[2*s].sum+tnode[2*s+1].sum;//用up,和down就更好理解
    } //这样就不需要放回了,更简单了...
    
    
    int find(int b,int d,int s)
    {
        if(tnode[s].b==b&&tnode[s].d==d)
        {
            return tnode[s].sum;
        }
        if(tnode[s].flag!=0)
        {
            tnode[s].flag=0;
            tnode[2*s].flag^=1;
            tnode[2*s].sum=(tnode[2*s].d-tnode[2*s].b+1)-tnode[2*s].sum;
    
            tnode[2*s+1].flag^=1;
            tnode[2*s+1].sum=(tnode[2*s+1].d-tnode[2*s+1].b+1)-tnode[2*s+1].sum;
        }
        if(tnode[s].mid>=d)
            return find(b,d,s*2);
        else if(tnode[s].mid+1<=b)
            return find(b,d,2*s+1);
        else return find(b,tnode[s].mid,s*2)+find(tnode[s].mid+1,d,2*s+1);
    }
    
    
    int main()
    {
        //freopen("//home//chen//Desktop//ACM//in.text","r",stdin);
        //freopen("//home//chen//Desktop//ACM//out.text","w",stdout);
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            cnt=0;
            id=0;
            memset(pre,-1,sizeof(pre));
            for(int i=2;i<=n;i++)
            {
                int tmp;
                scanf("%d",&tmp);
                add_edge(i,tmp);
                add_edge(tmp,i);
            }
            dfs(1,1);
            ///////////////
            built(1,n,1);
            for(int i=0;i<m;i++)
            {
                char sel;
                int tmp;
                cin>>sel;
                scanf("%d",&tmp);
                if(sel=='o')
                {
                    insert(savex[tmp],savey[tmp],1);
                }
                else
                {
                    printf("%d
    ",find(savex[tmp],savey[tmp],1));
                }
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    SlideShowExtender制作相册
    Response.Redirect(),Server.Transfer(),Server.Execute()的区别
    虚方法,抽象类,多态性
    gridview获取当前行索引的方法
    AutoQueryTextBox(AjaxPro.dll)非常值得研究的javascript代码
    abstract & virtual & override & new比较(转)
    Asp.net技巧:gridview获取当前行索引的方法
    js 获取浏览器高度和宽度值
    深入理解abstract class和interface
    c++ 静态数据成员和静态成员函数
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/3188821.html
Copyright © 2011-2022 走看看