zoukankan      html  css  js  c++  java
  • J

    J - Super Mario HDU - 4417 

    这个题目我开始直接暴力,然后就超时了,不知道该怎么做,直接看了题解,这个习惯其实不太好。

    不过网上的思路真的很厉害,看完之后有点伤心,感觉自己应该可以写的,但是没有写出来。

    因为我们要查找一个区间小于等于c的数有多少个,这种区间处理可以用线段树很好的解决,

    但是怎么解决呢,我习惯性的直接建树,然后再想怎么做,其实这样不对,

    线段树对于我们来说是一个解决问题的工具,不要本末倒置了。

    我们想查找一个区间小于等于c的数的个数,用线段树查询很简单,但是怎么建树才可以

    让我们每次查询都得到想要的结果呢,这个肯定是不能直接把这个墙的高度直接建树的,应该要先处理一下。

    我们可以把查询的高度按升序排序,这样线段树之前更新过的值就不会影响后面的值了。

    但是线段树怎么更新呢,这个也可以按升序对墙排个序,这样就解决问题了。

    这个思路其实没有特别难想。。。

    代码很好敲,但是要注意不要漏掉了,也许都已经更新完了,但是这个答案没有在for循环里面找到。

    这个要注意!!!

    然后这个题目还可以用主席树写

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5+10;
    ll sum[maxn*8], ans[maxn];
    int n, m;
    struct node
    {
        ll num, id;
    }a[maxn];
    struct edge
    {
        ll l, r, h, id;
        edge(ll l=0,ll r=0,ll h=0,ll id=0):l(l),r(r),h(h),id(id){}
    }ex[maxn];
    
    bool cmp(node a,node b)
    {
        return a.num < b.num;
    }
    
    bool cmp1(edge a,edge b)
    {
        return a.h < b.h;
    }
    
    void update(int id,int l,int r,int pos)
    {
        if(l==r)
        {
            sum[id] = 1;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) update(id << 1, l, mid, pos);
        else update(id << 1 | 1, mid + 1, r, pos);
        sum[id] = sum[id << 1] + sum[id << 1 | 1];
        //printf("sum[%d]=%d
    ", id, sum[id]);
    }
    
    ll query(int id,int l,int r,int x,int y)
    {
        if (x <= l && y >= r) return sum[id];
        int mid = (l + r) >> 1;
        int ans = 0;
        if (x <= mid) ans += query(id << 1, l, mid, x, y);
        if (y > mid) ans += query(id << 1 | 1, mid + 1, r, x, y);
        return ans;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        for(int cas=1;cas<=t;cas++)
        {
            memset(ans, 0, sizeof(ans));
            memset(sum, 0, sizeof(sum));
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) scanf("%lld", &a[i].num), a[i].id = i;
            for (int i = 1; i <= m; i++) {
                ll l, r, h;
                scanf("%lld%lld%lld", &l, &r, &h);
                l++, r++;
                ex[i] = edge(l, r, h, i);
            }
            sort(a + 1, a + 1 + n, cmp);
            sort(ex + 1, ex + 1 + m, cmp1);
            printf("Case %d:
    ", cas);
            int k = 1;
            for(int i=1;i<=n;i++)
            {
                while(a[i].num>ex[k].h&&k<=m)
                {
                    ans[ex[k].id] = query(1, 1, n, ex[k].l, ex[k].r);
                    k++;
                }
                update(1, 1, n, a[i].id);
            }
            for (int i = k; i <= m; i++) ans[ex[i].id] = query(1, 1, n, ex[i].l, ex[i].r);//这个注意不要丢掉了!!!
            for (int i = 1; i <= m; i++) printf("%lld
    ", ans[i]);
        }
        return 0;
    }
    线段树
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 10;
    int n, m, root[maxn], a[maxn], b[maxn], cnt;
    int sum[maxn << 5], lc[maxn << 5], rc[maxn << 5];
    
    void build(int &rt,int l,int r)
    {
        rt = ++cnt;
        sum[rt] = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(lc[rt], l, mid);
        build(rc[rt], mid + 1, r);
        // printf("rt=%d l=%d r=%d
    ",rt,l,r);
    }
    
    int update(int rt,int l,int r,int pos)
    {
        // printf("ww  rt=%d l=%d r=%d pos=%d
    ", rt, l, r, pos);
        int id = ++cnt;
        sum[id] = sum[rt] + 1;
        // printf("rt=%d sum[%d]=%d
    ", rt, id, sum[id]);
        lc[id] = lc[rt], rc[id] = rc[rt];
        if (l == r) return id;
        int mid = (l + r) >> 1;
        // printf("mid=%d rt=%d l=%d r=%d pos=%d
    ", mid,rt,l,r,pos);
        if (pos <= mid) lc[id] = update(lc[id], l, mid, pos);
        else rc[id] = update(rc[id], mid + 1, r, pos);
        // printf("rt=%d l=%d r=%d pos=%d
    ", rt, l, r, pos);
        return id;
    }
    
    int query(int l,int r,int u,int v,int h)
    {
        int mid = (l + r) >> 1;
        int x = sum[lc[v]] - sum[lc[u]];
        if (l == r) return sum[v] - sum[u];
        int ans = 0;
        if (h <= mid) ans = query(l, mid, lc[u], lc[v], h);
        else ans = x + query(mid + 1, r, rc[u], rc[v], h);
        return ans;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        for(int cas=1;cas<=t;cas++)
        {
            cnt = 0;
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
            sort(b + 1, b + 1 + n);
            int len = unique(b + 1, b + 1 + n) - b - 1;
            build(root[0], 1, len);
            // printf("
    
    ");
            for (int i = 1; i <= n; i++) {
                a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b;
                //printf("a[%d]=%d
    ", i, a[i]);
                root[i] = update(root[i - 1], 1, len, a[i]);
                // printf("sum[%d]=%d
    ", root[i], sum[root[i]]);
                // printf("
    ");
            }
            printf("Case %d:
    ", cas);
            while(m--)
            {
                int l, r, h;
                scanf("%d%d%d", &l, &r, &h);
                l++, r++;
                h = upper_bound(b + 1, b + 1 + len, h) - b - 1;
                if (h == 0) printf("0
    ");
                else printf("%d
    ", query(1, len, root[l - 1], root[r], h));
            }
        }
        return 0;
    }
    主席树
  • 相关阅读:
    面向对象
    tomcat启动时的java_home和jre_home错误
    C#获取当前程序运行路径的方法集合(转)
    Windows Media Player 打不开怎么办
    CGI/MIME/servlet术语解释
    HTTP 无法注册 URL http://+:8000/。进程不具有此命名空间的访问权限
    使用QuartZ.net来做定时计划任务 ; 值不能为 null。 参数名: assemblyString
    cz.msebera.android.httpclient.conn.ConnectTimeoutException: Connect to /192.168.23.1:8080 timed out(Android访问后台一直说链接超时)
    Java的位运算符——&0xFF的运算与讲解
    android+myeclipse+mysql自定义控件下拉框的数据绑定
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11216876.html
Copyright © 2011-2022 走看看