zoukankan      html  css  js  c++  java
  • BZOJ4150 AMPPZ2014 The Staging 【线段树】*

    BZOJ4150 AMPPZ2014 The Staging


    Description

    在舞台上有n个枪手,第i个枪手瞄准了第p[i]个枪手,将于第u[i]秒开枪。一个枪手如果成功开枪,
    那么被瞄准的枪手会立刻死亡。
    现在给出q次修改操作,请在一开始和每次修改操作后统计出最后存活的枪手个数。

    Input

    第一行包含一个正整数n(1<=n<=200000),表示枪手的个数。
    第二行包含n个互不相同的正整数p[1],p[2],...,p[n](1<=p[i]<=n,p[i]!=i),依次表示每个枪手的目标。
    第三行包含n个正整数u[1],u[2],...,u[n](1<=u[i]<=109),依次表示每个枪手的开枪时间。
    接下来一行包含一个正整数q,表示修改操作的个数。
    接下来q行,每行包含两个正整数k,v(1<=k<=n,1<=v<=109),表示把u[k]修改为v。
    数据保证任何时刻任意两个枪手的开枪时间都不同。

    Output

    第一行包含一个正整数,即在进行修改之前最后存活的枪手个数。
    接下来q行,每行包含一个正整数,第i行输出在第i次修改之后最后存活的枪手个数。

    Sample Input

    4
    2 3 4 1
    1 2 3 4
    3
    1 8
    2 7
    3 6

    Sample Output

    2
    2
    1
    1


    线段树好题
    真的好
    上次好像是dcy还是谁的给我们考过一次
    然后无奈暴力50分
    考完听完评奖望之生畏也就没改留坑了
    结果这次cdsf又给我们考,因为不想接受暴零的未来
    所以拼命想,然后把它做出来了
    结果是好的


    接下来讲正事
    首先我们有很多的环
    然后我们考虑从中间的某一个点把这个环剖开
    然后变成一条链
    然后我们有许许多多的单点修改,全局查询。。。想到了啥
    线段树啊

    然后发现一个人是否存活之和它之前的人有没有机会发出炮弹有关
    所以对于一个区间,我们考虑维护左端点的人可以存活的时候,右端点的人是否存活,在这个时候区间中可以留下的人一共有多少,左端点的人不能存活同理,顺便维护一下一个区间的左右端点的u

    然后我们考虑怎么合并两个区间
    首先,对于左端点可以存活的时候,来看看左区间的右端点的人活不活的了,如果活的了就判断一下右区间的左端点可不可以活,然后统计贡献,左端点不可以存活同理

    有些细节太繁琐了,还是自己想想好了
    然后讨论区间一共可以活下多少人同理

    然后最后统计答案的时候,分类讨论一下最左端点和最右端点的情况统计一下贡献

    然后就可以滑稽了


    #include<bits/stdc++.h>
    using namespace std;
    #define N 200010
    struct Node{int id,tim;};
    bool operator < (Node a,Node b){return a.tim>b.tim;}
    int n,m,tot=0;
    int u[N],p[N],bel[N]={0},ans,res[N],newpos[N];
    bool vis[N];
    vector<int> ch[N];
    priority_queue<Node> q;
    int rt[N],ld[N<<2],rd[N<<2],siz1[N<<2],siz2[N<<2];
    int ul[N<<2],ur[N<<2];
    bool tmp1[N<<2],tmp2[N<<2];
    int tcnt=0;
    int st[N];
    void pushup(int t){
        ul[t]=ul[ld[t]];
        ur[t]=ur[rd[t]];
        //alive
        if(tmp1[ld[t]]){
            if(ur[ld[t]]<ul[rd[t]])tmp1[t]=tmp2[rd[t]];
            else tmp1[t]=tmp1[rd[t]];
        }else tmp1[t]=tmp1[rd[t]];
    
        if(tmp2[ld[t]]){
            if(ur[ld[t]]<ul[rd[t]])tmp2[t]=tmp2[rd[t]];
            else tmp2[t]=tmp1[rd[t]];
        }else tmp2[t]=tmp1[rd[t]];
        //siz
        if(tmp1[ld[t]]){
            if(ur[ld[t]]<ul[rd[t]])siz1[t]=siz1[ld[t]]+siz2[rd[t]];
            else siz1[t]=siz1[ld[t]]+siz1[rd[t]]-1;
        }else siz1[t]=siz1[ld[t]]+siz1[rd[t]];
    
        if(tmp2[ld[t]]){
            if(ur[ld[t]]<ul[rd[t]])siz2[t]=siz2[ld[t]]+siz2[rd[t]];
            else siz2[t]=siz2[ld[t]]+siz1[rd[t]]-1;
        }else siz2[t]=siz2[ld[t]]+siz1[rd[t]];
    }
    void build(int &t,int l,int r){
        if(l>r)return;
        t=++tcnt;
        if(l==r){
            tmp1[t]=1;tmp2[t]=0;
            siz1[t]=1;siz2[t]=0;
            ul[t]=ur[t]=u[st[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(ld[t],l,mid);
        build(rd[t],mid+1,r);
        pushup(t);
    }
    void modify(int t,int l,int r,int pos,int vl){
        if(l==r){ul[t]=ur[t]=vl;return;}
        int mid=(l+r)>>1;
        if(pos<=mid)modify(ld[t],l,mid,pos,vl);
        else modify(rd[t],mid+1,r,pos,vl);
        pushup(t);
    }
    void init(int &root,int t){
        int now=0;
        int u=ch[t][0],tmp=p[u];
        st[++now]=u;
        newpos[u]=now;
        while(tmp!=u){
            st[++now]=tmp;
            newpos[tmp]=now;
            tmp=p[tmp];
        }
        build(root,1,now);
    }
    int work(int t){
        t=rt[t];
        if(ur[t]<ul[t]){
            if(tmp2[t])return siz2[t];
            else return siz1[t];
        }else {
            if(tmp1[t])return siz1[t]-1;
            else return siz1[t];
        }
    }
    int fa[N],siz;
    int findfa(int x){
        if(fa[x]==x)return x;
        return fa[x]=findfa(fa[x]);
    }
    int main(){
        scanf("%d",&n);
        siz=n;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=n;i++){
            scanf("%d",&p[i]);
            int fi=findfa(i);
            int fpi=findfa(p[i]);
            if(fi!=fpi)fa[fpi]=fi;
        }
        for(int i=1;i<=n;i++){
            int fi=findfa(i);
            if(!bel[fi])bel[i]=bel[fi]=++tot;
            else bel[i]=bel[fi];
            ch[bel[i]].push_back(i);
        }
        for(int i=1;i<=n;i++)scanf("%d",&u[i]);
        for(int i=1;i<=tot;i++)init(rt[i],i);
        int ans=0;
        for(int i=1;i<=tot;i++)ans+=work(i);
        printf("%d
    ",ans);
        scanf("%d",&m);
        while(m--){
            int x,val;
            scanf("%d%d",&x,&val);
            int f=bel[x];x=newpos[x];
            ans-=work(f);
            modify(rt[f],1,(signed)ch[f].size(),x,val);
            ans+=work(f);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    ASP.Net Core "The type initializer for 'Gdip' threw an exception"
    ERROR 1698 (28000): Access denied for user 'root'@'localhost'
    彻底卸载Xubuntu Kubuntu
    Ubuntu MariaDB PhpMyAdmin
    VMware虚拟机复制后Linux无法上网
    Visual Studio 项目依赖
    Windows 10 关闭Hyper-V
    一个用python写的比特币均线指标
    关于PHP连接上MySQL但不能插入数据
    【原创】关于pyinstaller打包的程序执行出错问题,pyinstaller3.5只支持matplotlib3.0.2已经解决
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676283.html
Copyright © 2011-2022 走看看