zoukankan      html  css  js  c++  java
  • BZOJ 1875: [SDOI2009]HH去散步

    Time Limit: 20 Sec Memory Limit: 64 MB
    Submit: 2244 Solved: 1144
    [Submit][Status][Discuss]
    Description

    HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但
    是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每
    天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。 现在给你学校的地图(假设每条路的长度都
    是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径
    Input

    第一行:五个整数N,M,t,A,B。
    N表示学校里的路口的个数
    M表示学校里的 路的条数
    t表示HH想要散步的距离
    A表示散步的出发点
    B则表示散步的终点。
    接下来M行
    每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。
    数据保证Ai != Bi,但不保证任意两个路口之间至多只有一条路相连接。
    路口编号从0到N -1。
    同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。
    答案模45989。
    N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B
    Output

    一行,表示答案。

    Sample Input

    4 5 3 0 0

    0 1

    0 2

    0 3

    2 1

    3 2
    Sample Output

    4

    解题思路

    树状数组+离线,如果将询问按照l排序,那么后面出现的与前面相同的可以替代前面的,所以记录一个nxt[i]数组,表示i这个位置往后第一个与i元素相同的元素的下标,然后将询问按照l排序,每次将此时扫到的元素的nxt在树状数组里+1。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 1000005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,m,a[MAXN],nxt[MAXN],p[MAXN],mx,f[MAXN];
    struct Data{
        int l,r,id,ans;
    }data[MAXN];
    
    
    
    inline bool cmp(Data A,Data B){
        if(A.l==B.l) return A.r<B.r;
        return A.l<B.l;
    }
    
    inline bool cmp_(Data A,Data B){
        return A.id<B.id;
    }
    
    inline void update(int x,int y){
        for(;x<=n;x+=x&-x) f[x]+=y;
    }
    
    inline int query(int x){
        int ret=0;
        for(;x;x-=x&-x) ret+=f[x];
        return ret;
    }
    
    int main(){
        n=rd();
        for(register int i=1;i<=n;i++){
            a[i]=rd();
            mx=max(a[i],mx);
        }
        for(register int i=n;i;i--) nxt[i]=p[a[i]],p[a[i]]=i;
        for(register int i=1;i<=mx;i++) if(p[i]) update(p[i],1);
        m=rd();
        for(register int i=1;i<=m;i++)
            data[i].l=rd(),data[i].r=rd(),data[i].id=i;
        sort(data+1,data+1+m,cmp);
        int l=1;
        for(register int i=1;i<=m;i++){
            while(l<data[i].l){
                if(nxt[l]) update(nxt[l],1);
                l++;
            }
            data[i].ans=query(data[i].r)-query(data[i].l-1);
        }
        sort(data+1,data+1+m,cmp_);
        for(register int i=1;i<=m;i++)
            printf("%d
    ",data[i].ans);
        return 0;
    }
  • 相关阅读:
    让Extjs EditorGridPanel 编辑时支持方向键
    开发WebApp之PC客户端
    windows下mysql忘记root密码的解决方法
    TortoiseSVN使用svn+ssh协议连接服务器时重复提示输入密码
    jQuery Mobile页面跳转后未加载外部JS原因分析及解决
    在CentOS中安装与配置SVN的方法
    设置VMWARE通过桥接方式使用主机无线网卡上网
    关于sp_executesql与exec执行动态sql的区别--转载RascallySnake
    TreeView 点击触发父节点、子节点的连锁反应选中与取消
    Winform客户端发布与升级:ClickOnce
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676915.html
Copyright © 2011-2022 走看看