zoukankan      html  css  js  c++  java
  • 铁轨 清北学堂 线段树

    铁轨 清北学堂 线段树

    【题目描述】
    R 国的铁轨经常会进行重新修建。
    R 国是一个细长的国家,一共有 n 个城市排成一排,首都位于 1 号城市,相邻两个城市之间有铁路相连。
    每次新建铁轨的时候,一定是从首都开始修建,直到某一个城市为止,这其间的铁路都会变成新版本的设
    施,而旧设施会被拆除。然而,由于 R 国的工程师脑子不太好使,任意两种不同版本的铁路之间都无法连
    接,因此必须要进行换乘。
    现在给出你修建铁轨的操作,小 R 时不时第会想问你,如果在第 x 个城市到第 y 个城市之间随机选择一个
    城市乘车去往首都,则换乘次数期望是多少次?
    初始时所有城市都由同一种铁道设施相连接。

    【输入格式】
    第一行两个整数 n 和 m,代表城市的数量和操作的数量
    接下来 m 行,每行代表一个操作
    若第一个数为 0,则接下来接一个数 x,代表从 1 号城市到 x 号城市之间的铁路重新修建了。
    若第一个数为 1,则接下来接两个数 x 和 y,代表小 R 询问在第 x 个城市到第 y 个城市之间随机选择一个城
    市乘车去往首都,换乘的期望次数。

    【输出格式】
    对于每次询问,输出一行一个实数代表答案,保留四位小数

    容易想到用线段树维护区间换乘数和来计算期望,对于每次修建,我们将区间([1,x])覆盖为(0),对于剩下的区间([x+1, n]),我们发现换乘次数改变一定是同步的,于是我们区间减去(val[x+1]-1)即可(即将(x+1)修改为(1))。

    注意下放覆盖标记的写法

    void push_down(int x, int l, int r){
        if(lazy_cover[x]){
            tre[sl]=tre[sr]=0;
            lazy[sl]=lazy[sr]=0;
            lazy_cover[sl]=lazy_cover[sr]=1;
            lazy_cover[x]=0;
        }
        if(lazy[x]==0) return;
        int mid=(l+r)>>1;
    	tre[sl]+=lazy[x]*(mid-l+1);
    	lazy[sl]+=lazy[x];
    	tre[sr]+=lazy[x]*(r-(mid+1)+1);
    	lazy[sr]+=lazy[x];
        lazy[x]=0;
    }
    

    注意精度,JXOJ的数据是用double跑出来的,所以要用double

    #include <cstdio>
    #define MAXN 100010
    #define sl (x<<1)
    #define sr (x<<1|1)
    using namespace std;
    inline int read(){
        char ch=getchar();int s=0;
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
        return s;
    }
    int tre[MAXN*4];
    int lazy[MAXN*4];
    bool lazy_cover[MAXN*4];
    void push_down(int x, int l, int r){
        if(lazy_cover[x]){
            tre[sl]=tre[sr]=0;
            lazy[sl]=lazy[sr]=0;
            lazy_cover[sl]=lazy_cover[sr]=1;
            lazy_cover[x]=0;
        }
        if(lazy[x]==0) return;
        int mid=(l+r)>>1;
    	tre[sl]+=lazy[x]*(mid-l+1);
    	lazy[sl]+=lazy[x];
    	tre[sr]+=lazy[x]*(r-(mid+1)+1);
    	lazy[sr]+=lazy[x];
        lazy[x]=0;
    }
    void cover(int x, int l, int r, int cl, int cr){
        if(cl<=l&&r<=cr){
            tre[x]=0;
            lazy[x]=0;
            lazy_cover[x]=1;
            //printf("cover[%d,%d]=%d
    ", l, r, tre[x]);
            return;
        }
        push_down(x, l, r);
        int mid=(l+r)>>1;
        if(cl<=mid) cover(sl, l, mid, cl, cr);
        if(mid<cr) cover(sr, mid+1, r, cl, cr);
        tre[x]=tre[sl]+tre[sr];
        //printf("cover[%d,%d]=%d
    ", l, r, tre[x]);
    }
    void change(int x, int l, int r, int cl, int cr, int val){
        if(cl<=l&&r<=cr){
            tre[x]+=val*(r-l+1);
            lazy[x]+=val;
            return;
        }
        push_down(x, l, r);
        int mid=(l+r)>>1;
        if(cl<=mid) change(sl, l, mid, cl, cr, val);
        if(mid<cr) change(sr, mid+1, r, cl, cr, val);
        tre[x]=tre[sl]+tre[sr];
    }
    int query(int x, int l, int r, int ql, int qr){
        if(ql<=l&&r<=qr){
        	//printf("query[%d,%d]=%d
    ", l, r, tre[x]);
            return tre[x];
        }
        push_down(x, l, r);
        int mid=(l+r)>>1;
        int res=0;
        if(ql<=mid) res+=query(sl, l, mid, ql, qr);
        if(mid<qr) res+=query(sr, mid+1, r, ql, qr);
        //printf("query[%d,%d]=%d
    ", l, r, res);
        return res;
    }
    inline void myswap(int &a, int &b){
        int t=a;
        a=b;
        b=t;
    }
    int n,m;
    int s[MAXN],top;
    int main(){
        scanf("%d %d", &n, &m);
        while(m--){
            int opt,x,y;
            scanf("%d", &opt);
            if(opt==0){
                scanf("%d", &x);
                cover(1, 1, n, 1, x);
    			change(1, 1, n, x+1, n, 1-query(1, 1, n, x+1, x+1));
            }else{
                scanf("%d %d", &x, &y);
                if(x>y) myswap(x, y);
                printf("%.4lf
    ", (double)query(1, 1, n, x, y)*1.0/(y-x+1));
            } 
        }
        return 0;
    }
    
  • 相关阅读:
    10本Java程序员有助成长的书
    Java最新学习路线图
    2020最新版Java学习路线图
    自己的Java学习经历
    Java并发编程学习教程
    2020年最新Java学习路线
    Java Stream入门知识讲解
    你可能不知道的java14新特性
    Windows下获取当前目录路径,及创建新的文件夹方法
    win10下_findnext报oxc0000005错误解决
  • 原文地址:https://www.cnblogs.com/santiego/p/11671101.html
Copyright © 2011-2022 走看看