• Playoff Tournament (详细版线段树)


    k2 
    k
      teams participate in a playoff tournament. The tournament consists of 2^k - 12 
    k
     −1 games. They are held as follows: first of all, the teams are split into pairs: team 11 plays against team 22, team 33 plays against team 44 (exactly in this order), and so on (so, 2^{k-1}2 
    k−1
      games are played in that phase). When a team loses a game, it is eliminated, and each game results in elimination of one team (there are no ties). After that, only 2^{k-1}2 
    k−1
      teams remain. If only one team remains, it is declared the champion; otherwise, 2^{k-2}2 
    k−2
      games are played: in the first one of them, the winner of the game "11 vs 22" plays against the winner of the game "33 vs 44", then the winner of the game "55 vs 66" plays against the winner of the game "77 vs 88", and so on. This process repeats until only one team remains.
    
    For example, this picture describes the chronological order of games with k = 3k=3:
    
    
    Let the string ss consisting of 2^k - 12 
    k
     −1 characters describe the results of the games in chronological order as follows:
    
    if s_is 
    i
    ​
      is 0, then the team with lower index wins the ii-th game;
    if s_is 
    i
    ​
      is 1, then the team with greater index wins the ii-th game;
    if s_is 
    i
    ​
      is ?, then the result of the ii-th game is unknown (any team could win this game).
    Let f(s)f(s) be the number of possible winners of the tournament described by the string ss. A team ii is a possible winner of the tournament if it is possible to replace every ? with either 1 or 0 in such a way that team ii is the champion.
    
    You are given the initial state of the string ss. You have to process qq queries of the following form:
    
    pp cc — replace s_ps 
    p
    ​
      with character cc, and print f(s)f(s) as the result of the query.
    Input
    The first line contains one integer kk (1 \le k \le 181≤k≤18).
    
    The second line contains a string consisting of 2^k - 12 
    k
     −1 characters — the initial state of the string ss. Each character is either ?, 0, or 1.
    
    The third line contains one integer qq (1 \le q \le 2 \cdot 10^51≤q≤210 
    5
     ) — the number of queries.
    
    Then qq lines follow, the ii-th line contains an integer pp and a character cc (1 \le p \le 2^k - 11≤p≤2 
    k
     −1; cc is either ?, 0, or 1), describing the ii-th query.
    
    Output
    For each query, print one integer — f(s)f(s).
    View problem

    思路:

    • 这道题乍一看有分治的思想
    • 为了方便处理就利用线段树(每一个节点可以存储很多信息,这就是他的魅力,应付各种类型的题)
    • 具体处理: 每一个节点要存储 左儿子的真实值 和右儿子的真实值,和自己的真实值(更具0,1,?)
    • 如何将 0,1,?弄到对应的节点上呢?利用我下面这个建树的方式 (i<<1,i<<1|1)

      7 那里是 111, 写彪了 qwq

     可以看到这个是非常有规律的,每一层的长度和最左边的值和上面一层2倍关系,具体处理看代码

    #include <bits/stdc++.h>
    using namespace std;
    #define ri register int 
    #define M 302144
    
    template <class G> void read(G &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=f?-x:x;
        return ;
    }
    
    struct dain{
        int l,r;
        int val[5];// 左,右,2个,真实值。 
        char bj;
        int flag;
    }p[M*4];
    int n,cur;
    char  s[M];
    
    int num[M*4];
    void build(int l,int r,int i)
    {
        int mid=(l+r)>>1;
        p[i].l=l;p[i].r=r;
        if(l==r) 
        {
            p[i].val[4]=1;
            return ;
        }
        num[p[i].flag]=r;
        build(l,mid,i<<1);
        build(mid+1,r,i<<1|1);
        p[i].val[1]=p[i<<1].val[4];
        p[i].val[2]=p[i<<1|1].val[4];
        p[i].val[3]=p[i].val[1]+p[i].val[2];
        if(p[i].bj=='0') p[i].val[4]=p[i<<1].val[4];
        if(p[i].bj=='1') p[i].val[4]=p[i<<1|1].val[4];
        if(p[i].bj=='?') p[i].val[4]=p[i].val[1]+p[i].val[2];
    }
    char c;
    void qu(int i,int a)
    {
        if(p[i].flag==a)
        {
            p[i].bj=c;
            if(c=='0')
            {
                p[i].val[4]=p[i].val[1];
                return ;
            }
            if(c=='1'){
                p[i].val[4]=p[i].val[2];
                return ;
            } 
            if(c=='?'){ 
            p[i].val[4]=p[i].val[3];
            return ;
            } 
        }
        int mid=(p[i].r+p[i].l)>>1;
        if(num[a]<=mid)
        {
            qu(i<<1,a);
        }
        else
        {
            qu(i<<1|1,a);
        }
        p[i].val[1]=p[i<<1].val[4];
        p[i].val[2]=p[i<<1|1].val[4];
        p[i].val[3]=p[i].val[1]+p[i].val[2];
        if(p[i].bj=='0') p[i].val[4]=p[i<<1].val[4];
        if(p[i].bj=='1') p[i].val[4]=p[i<<1|1].val[4];
        if(p[i].bj=='?') p[i].val[4]=p[i].val[1]+p[i].val[2];    
    }
    int m;
    int main(){
        
        read(n);
        for(ri i=1;i<(1<<n);i++)
        {
            cin>>s[i];
        }
        read(m);
        cur=0;
        for(ri i=(1<<(n-1));i>=1;i>>=1)
        {
            for(ri j=i;j<i*2;j++)
            {
                p[j].flag=++cur;
                p[j].bj=s[cur];
            }
        }
        build(1,(1<<n),1);
        
        for(ri i=1;i<=m;i++)
        {
            int a;
            cin>>a>>c;
            qu(1,a);
            printf("%d\n",p[1].val[4]);
        }
        return 0;
    }
    View Code

     后记:

    • 如何更具题目来建立树,和相关的转移,修改,是很重要的实现能力。
  • 相关阅读:
    http返回码
    JAVA获取当前系统时间System.currentTimeMillis()以及获取运行时间
    【Jsoup】Jsoup解析Html标签(Java后台解析)
    字节、字、位、比特,这四者之间的关系
    Java中字符编码和字符串所占字节数 .
    判断一个字符串是否为全英文的工具
    汉语转拼音(全转与只转首个字母)工具类
    Page的生命周期及相关事件苛
    PHP设计模式——策略模式
    java生产者消费者问题代码分析
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/16171444.html
Copyright © 2020-2023  润新知