zoukankan      html  css  js  c++  java
  • 2019 Multi-University Training Contest 2

    http://acm.hdu.edu.cn/showproblem.php?pid=6601

    首先要贪心地想,题目要最长的边长,那么要怎么构造呢?在一段连续的区间里面,一定是拿出最长的三根出来比,这样一定是最大的(废话)。而且假如组成三角形失败的话最长的那根这次就没有用了。

    考虑临界情况,也就是刚刚好不能组成三角形的时候,要在1e9内尽可能地安排多的棒子,那就不妨设为:1,1,2,3,5,8……也就是斐波那契数列。可以打出来发现在43项左右的时候已经接近1e9了。

    也就是每个区间真正有用的只是最长的50根。

    考虑对每个区间建立线段树,线段树里面就存当前区间最长的至多50根。

    要动态管理这些区间vector实现的版本的确非常方便。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXM = 100000;
    int a[MAXM + 5];
    vector<int> st[(MAXM << 2) + 5];
    
    void build(int o, int l, int r) {
        if(l == r) {
            st[o].resize(r - l + 1);
            st[o][0] = a[l];
        } else {
            int m = (l + r) >> 1;
            build(o << 1, l, m);
            build(o << 1 | 1, m + 1, r);
            st[o].resize(min(100,r - l + 1));
            merge(st[o << 1].begin(), st[o << 1] .end(),
                  st[o << 1 | 1].begin(), st[o << 1 | 1] .end(),
                  st[o].begin(), greater<int>());
            st[o].resize(min(50, r - l + 1));
        }
    }
    
    int used[MAXM], usedtop, it[MAXM];
    
    void query(int o, int l, int r, int a, int b) {
        if(a <= l && r <= b) {
            used[++usedtop] = o, it[usedtop] = 0;
        } else {
            int m = (l + r) >> 1;
            if(a <= m)
                query(o << 1, l, m, a, b);
            if(b >= m + 1)
                query(o << 1 | 1, m + 1, r, a, b);
        }
    }
    
    int val[MAXM], valtop;
    
    ll answer() {
        valtop = 0;
        bool fail = 0;
        int t = 50;
        while(t-- && !fail) {
            fail = 1;
            int maxval = 0, maxid = 0;
            for(int i = 1; i <= usedtop; ++i) {
                if(it[i] < st[used[i]].size()) {
                    if(st[used[i]][it[i]] > maxval) {
                        maxval = st[used[i]][it[i]];
                        maxid = i;
                    }
                    fail = 0;
                }
            }
            if(!fail) {
                val[++valtop] = maxval;
                ++it[maxid];
            }
        }
        for(int i = 1; i + 2 <= valtop; ++i)
            if(val[i + 1] + val[i + 2] > val[i])
                return (ll)val[i] + val[i + 1] + val[i + 2];
        return -1;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, q;
        while(~scanf("%d%d", &n, &q)) {
            for(int i = 1; i <= n; ++i)
                scanf("%d", &a[i]);
            build(1, 1, n);
            for(int i = 1; i <= q; ++i) {
                int l, r;
                scanf("%d%d", &l, &r);
                usedtop = 0;
                query(1, 1, n, l, r);
                printf("%lld
    ", answer());
            }
        }
        return 0;
    }
    

    不用vector的又慢又卡内存???或许跟手动的merge有关,把这个换成STL做对照可能会更快。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXM = 100000;
    int a[MAXM + 5], st[(MAXM << 2) + 5][50 + 5], sttop[(MAXM << 2) + 5];
    
    int _merge(int a[], int as, int b[], int bs, int c[]) {
        int i = 1, j = 1, k = 1;
        while((k <= 50) && (i <= as || j <= bs)) {
            if(i > as) {
                c[k] = b[j];
                ++j;
                ++k;
            } else if(j > bs) {
                c[k] = a[i];
                ++i;
                ++k;
            } else if(a[i] >= b[j]) {
                c[k] = a[i];
                ++i;
                ++k;
            } else {
                c[k] = b[j];
                ++j;
                ++k;
            }
        }
        return k;
    }
    
    void build(int o, int l, int r) {
        if(l == r) {
            sttop[o] = 1;
            st[o][1] = a[l];
        } else {
            int m = (l + r) >> 1;
            build(o << 1, l, m);
            build(o << 1 | 1, m + 1, r);
            sttop[o] = _merge(st[o << 1], sttop[o << 1],
                              st[o << 1 | 1], sttop[o << 1 | 1],
                              st[o]);
    //        printf("[%d,%d]
    ", l, r);
    //        for(int i = 1; i <= sttop[o]; ++i) {
    //            printf(" %d", st[o][i]);
    //        }
    //        printf("
    
    ");
        }
    }
    
    int used[MAXM], usedtop, it[MAXM];
    
    void query(int o, int l, int r, int a, int b) {
        if(a <= l && r <= b) {
            used[++usedtop] = o, it[usedtop] = 1;
        } else {
            int m = (l + r) >> 1;
            if(a <= m)
                query(o << 1, l, m, a, b);
            if(b >= m + 1)
                query(o << 1 | 1, m + 1, r, a, b);
        }
    }
    
    int val[MAXM], valtop;
    
    ll answer() {
        valtop = 0;
        bool fail = 0;
        int t = 50;
        while(t-- && !fail) {
            fail = 1;
            int maxval = 0, maxid = 0;
            for(int i = 1; i <= usedtop; ++i) {
                if(it[i] <= sttop[used[i]]) {
                    if(st[used[i]][it[i]] > maxval) {
                        maxval = st[used[i]][it[i]];
                        maxid = i;
                    }
                    fail = 0;
                }
            }
            if(!fail) {
                val[++valtop] = maxval;
                ++it[maxid];
            }
        }
        for(int i = 1; i + 2 <= valtop; ++i)
            if(val[i + 1] + val[i + 2] > val[i])
                return (ll)val[i] + val[i + 1] + val[i + 2];
        return -1;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, q;
        while(~scanf("%d%d", &n, &q)) {
            for(int i = 1; i <= n; ++i)
                scanf("%d", &a[i]);
            build(1, 1, n);
            for(int i = 1; i <= q; ++i) {
                int l, r;
                scanf("%d%d", &l, &r);
                usedtop = 0;
                query(1, 1, n, l, r);
                printf("%lld
    ", answer());
            }
        }
        return 0;
    }
    

    草,更慢,更浪费内存。让我对vector刮目相看。看来预先resize的vector是速度足够惊人的。

  • 相关阅读:
    移动端拖拽
    原生js增加,移除类名
    js自执行函数
    页面加载初始化方法
    writing-mode,文字竖直书写,字符之间距离,单词之间距离
    滚动鼠标达到一点范围时的跑秒效果,从0开始一直加在规定时间内加到最大值
    haley解决中文字段名称字数不同时两端对齐的问题
    常用的一些css实现的小效果,比如三角形,小三角,阴影等
    html几个比较常用的颜色名称
    Spring--通过注解来配置bean
  • 原文地址:https://www.cnblogs.com/Yinku/p/11240470.html
Copyright © 2011-2022 走看看