zoukankan      html  css  js  c++  java
  • 暑假N天乐【比赛篇】 —— 2019牛客暑期多校训练营(第七场)

    以下题解包括:(A B C D E J)

    另:(H【Pair】数位dp 待补) 毕竟我还不会

    比赛地址: https://ac.nowcoder.com/acm/contest/887#question

    【A】 String 最小表示法

    给定一个字符串,要把它分成最少段的最小表示法串,输出分段之后的字符串。

    从前往后依次枚举,不断缩短长度直到当前前缀为最小表示法即可,然后输出再从当前末尾开始判断。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    char s[205];
    string temp;
    int l;
    
    int get_min() {
        int i = 0, j = 1;
        int k = 0;
        while(i < l && j < l && k < l) {
            int t = temp[(i+k)%l] - temp[(j+k)%l];
            if(t == 0) {
                k ++;
            }
            else {
                if(t > 0) {
                    i = i + k + 1;
                }
                else {
                    j = j + k + 1;
                }
                k = 0;
                if(i == j) {
                    j ++;
                }
            }
        }
        return i < j ? i : j;
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            scanf("%s", s);
            int n = strlen(s);
            int pos = 0;
            while(1) {
                temp = "";
                for(int i = pos; i < n; i++) {
                    temp = temp + s[i];
                }
                l = temp.length();
                while(get_min() != 0) {
                    l--;
                }
                pos = pos + l;
                for(int i = 0; i < l; i ++) {
                    cout << temp[i];
                }
                if(pos == n) {
                    printf("
    ");
                    break;
                }
                else {
                    printf(" ");
                }
            }
        }
        return 0;
    }
    

    【B】 Irreducible Polynomial 数学

    给定一个一元 (n) 次方程,问能不能把它分解成连乘的形式。

    又是个定理题,次数大于等于 3 一定不行,等于 1 一定可以,等于二的时候需要判断 (b^2 - 4ac < 0) 是否成立,若成立,则可以。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
     
    int a[30];
     
    int main() {0;
    }
        int t;
        scanf("%d", &t);
        while(t--) {
            int n;
            scanf("%d", &n);
            for(int i = n; i >= 0; i--) {
                scanf("%d", &a[i]);
            }
            if(n >= 3) {
                printf("No
    ");
                continue;
            }
            if(n == 1) {
                printf("Yes
    ");
                continue;
            }
            if(a[1]*a[1]-4*a[0]*a[2] < 0) {
                printf("Yes
    ");
            }
            else {
                printf("No
    ");
            }
        }
        return 0;
    }
    

    【C】 Governing sand 贪心

    我也不知道为什么比赛时候没看到 "c <= 200" 这个条件,然后队友敲了个权值线段树维护,虽然过了也是浪费了挺多时间的,还把学弟坑了...以下是赛后写的正解(大概)。

    给定 (n) 种树,每种都有它的高度 (h(leq1e^9)),砍倒的费用 (c(leq 200))以及数量 (p(leq 1e^9))。现在需要让最高的树的数量占比超过 50%,问最小花费是多少。

    其实就是各种排序贪心一下就好了。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    const int maxn = 1e5+5;
    
    int n;
    ll sum[maxn];
    ll cost[205];
    ll numh[maxn];
    vector<ll> v;
    struct node {
        ll h, c, p;
        bool operator < (const node &q) const {
            return h < q.h;
        }
    }a[maxn];
    
    int getid(ll x) {
        return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
    }
    
    int main() {
        while(~scanf("%d", &n)) {
            v.clear();
            for(int i = 1; i <= n; i++) {
                scanf("%lld%lld%lld", &a[i].h, &a[i].c, &a[i].p);
                v.push_back(a[i].h);
            }
            sort(a+1, a+1+n);
            sort(v.begin(), v.end());
            v.erase(unique(v.begin(), v.end()), v.end());
            memset(sum, 0, sizeof(sum));
            memset(numh, 0, sizeof(numh));
            for(int i = 1; i <= n; i++) {
                int id = getid(a[i].h);
                sum[id] += sum[id-1] + 1ll*a[i].p*a[i].c;
                numh[id] += numh[id-1] + 1ll*a[i].p;
            }
            ll ans = 1e18;
            memset(cost, 0, sizeof(cost));
            int new_n = v.size();
            for(int i = 1; i <= n; i++) {
                int id = getid(a[i].h);
                ll temp = sum[new_n] - sum[id]; // 删掉所有比它高的树的代价
                ll num = numh[id] - numh[id-1]; // 这种高度的树的数量
                ll num_small = numh[id-1];      // 比他矮的树的数量
                // cout << temp << "  " << num << "  " << num_small << endl;
                if(num > num_small) {           // 不用砍了
                    ans = min(ans, temp);   
                    cost[a[i].c] += 1ll*a[i].p;
                    continue;
                }
                ll more = num_small - num + 1;  // 需要砍掉多少
                for(int j = 1; j <= 200; j++) {
                    if(cost[j] == 0) {
                        continue;
                    }
                    if(more - cost[j] >= 0) {
                        more -= cost[j];
                        temp = temp + cost[j]*j;
                    }
                    else {
                        temp = temp + more*j;
                        more = 0;
                    }
                    if(more == 0) {
                        break;
                    }
                }
                cost[a[i].c] += 1ll*a[i].p;
                ans = min(ans, temp);
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    【D】 Number 水题

    水题不写了。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    int get(int x) {
    	int res = 0;
    	while(x) {
    		res++;
    		x /= 10;
    	}
    	return res;
    }
    
    int main() {
    	int n, p;
    	while(~scanf("%d%d", &n, &p)) {
    		int l = get(p);
    		if(l > n) {
    			printf("T_T
    ");
    			continue;
    		}
    		printf("%d", p);
    		for(int i = l+1; i <= n; i++) {
    			printf("0");
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    

    【E】 Find the median 线段树

    参考:http://keyblog.cn/article-189.html

    题目花里胡哨的,其实就是给定两个数组 L,R和一个空序列,对于第 (i) 对 LR 来说,把 ([L_i,R_i]) 中的每个数加入序列,然后输出当前序列中的中位数。

    主要是写起来麻烦,一些 +1/-1 会很容易错,尤其是我这种使用 (vector) 离散化的,我是多插了一个 -1 让下标从 1 开始,这样或者用数组可以规避很多 +1/-1。具体实现看代码。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    const int maxn = 8e5+5;
    
    ll x[maxn], y[maxn];
    ll val[maxn<<2], lazy[maxn<<2];
    vector<ll> v;
    
    int getid(ll x) {
        return lower_bound(v.begin(), v.end(), x) - v.begin();
    }
    
    void pushup(int rt) {
        val[rt] = val[rt<<1] + val[rt<<1|1];
    }
    
    void pushdown(int l, int r, int rt) {
        int mid = (l+r) >> 1;
        val[rt<<1] += (v[mid]-v[l])*lazy[rt];
        val[rt<<1|1] += (v[r]-v[mid])*lazy[rt];
        lazy[rt<<1] += lazy[rt];
        lazy[rt<<1|1] += lazy[rt];
        lazy[rt] = 0;
    }
    
    void build(int l, int r, int rt) {
        if(l == r) {
            val[rt] = lazy[rt] = 0;
            return ;
        }
        int mid = (l+r) >> 1;
        build(l, mid, rt<<1);
        build(mid+1, r, rt<<1|1);
        pushup(rt);
    }
    
    void update(int L, int R, int l, int r, int rt) {
        if(L <= l && r-1 <= R) {
            val[rt] += (v[r]-v[l]);
            lazy[rt] ++;
            return ;
        }
        if(lazy[rt]) {
            pushdown(l, r, rt);
        }
        int mid = (l+r) >> 1;
        if(L < mid) {
            update(L, R, l, mid, rt<<1);
        }
        if(R >= mid) {
            update(L, R, mid, r, rt<<1|1);
        }
        pushup(rt);
    }
    
    ll query(int l, int r, int rt, ll x) {      // 找第 x 大的数
        if(l == r-1) {
            ll t = val[rt] / (v[r]-v[l]);
            return v[l] + (x-1)/t;
        }
        if(lazy[rt]) {
            pushdown(l, r, rt);
        }
        int mid = (l+r) >> 1;
        if(val[rt<<1] >= x) {
            return query(l, mid, rt<<1, x);
        }
        else {
            return query(mid, r, rt<<1|1, x-val[rt<<1]);
        }
    }
    
    int main() {
        int n;
        scanf("%d", &n);
        v.clear();
        ll a1, b1, c1, m1;
        ll a2, b2, c2, m2;
        scanf("%lld%lld%lld%lld%lld%lld", &x[1], &x[2], &a1, &b1, &c1, &m1);
        scanf("%lld%lld%lld%lld%lld%lld", &y[1], &y[2], &a2, &b2, &c2, &m2);
        for(int i = 3; i <= n; i++) {
            x[i] = (a1*x[i-1]+b1*x[i-2]+c1) % m1;
            y[i] = (a2*y[i-1]+b2*y[i-2]+c2) % m2;
        }
        for(int i = 1; i <= n; i++) {
             ll tx = x[i];
            ll ty = y[i];
            x[i] = min(tx, ty) + 1;
            y[i] = max(tx, ty) + 1 + 1; // 多 +1 方便区间操作
            v.push_back(x[i]);
            v.push_back(y[i]);
        }
        v.push_back(-1);
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        int new_n = v.size();
        ll sum = 0;
        build(1, new_n, 1);
        for(int i = 1; i <= n; i++) {
            int l = getid(x[i]);
            int r = getid(y[i]);
            update(l, r-1, 1, new_n, 1);
            sum = sum + (v[r] - v[l]);
            printf("%lld
    ", query(1, new_n, 1, (sum+1)/2));
        }
        return 0;
    }
    

    【J】 A+B problem 水题

    其实不是很想把它叫做水题,毕竟把我给卡了,明明 10 行搞定的东西,脑子一抽写了快 100 行,多花了不知道多久...以下代码为赛后补题

    水题不写了。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    ll f(ll x) {
        ll res = 0;
        while(x) {
            res = res*10 + x%10;
            x /= 10;
        }
        return res;
    }
    
    int main() {
        ll a, b;
        int t;
        scanf("%d", &t);
        while(t--) {
            scanf("%lld%lld", &a, &b);
            printf("%lld
    ", f(f(a)+f(b)));
        }
        return 0;
    }
    
  • 相关阅读:
    JQ用法
    js查漏补缺【未完】
    VSCode里面HTML添加CSS时没有提示
    CSS查漏补缺【未完】
    HTML查漏补缺 【未完】
    Android Bitmap 全面解析(二)加载多张图片的缓存处理
    android Paint 详解
    Android Bitmap 全面解析(一)加载大尺寸图片
    图片处理框架
    [项目总结]论Android Adapter notifyDataSetChanged与notifyDataSetInvalidated无效原因
  • 原文地址:https://www.cnblogs.com/Decray/p/11366001.html
Copyright © 2011-2022 走看看