zoukankan      html  css  js  c++  java
  • 省选测试47


    又差不多是0分,两天加起来总共8分,我也是没谁了
    T1又写出正解,没用c++11编译,于是CE了,T3看不懂题,找了huge,解释错了之后我就40变0分,
    T2的n2很好像,可惜实在是没时间想了,于是写了个最裸的暴力,成为两天里唯一的得分点

    A 旅游

    题目大意 : 要从x到y,每次最多走到后面第z个城市,走每个城市都会付出a的代价,走某些城市会有收益,问到终点的最大收益

    • n2的dp很好想,设f[i]为走到第i个有收益的城市所得的最大收益,转移也就很显然

    [f[i]=max_{j=0}^{i-1}f[j]+wleft lceil frac{pos[i]-pos[j]}{z} ight ceil ]

    • 想斜率优化,发现这个值关于pos[i]的函数是每z个都是平的,然后降a,然后z个不变,然后降a这样,不是很能斜率优化

    • 于是我把他们都表示在1到z里,然后只取有用的(就是最上面的),set维护,查询的时候在set里二分,写起来很鬼畜

    • 正解思路和我我差不多,只是他是用线段树维护,常数较大

    Code

    Show Code
    #include <set>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; (c < '0' || c > '9'); c = getchar()) if (c == '-') f = -1;
        for (;!(c < '0' || c > '9'); c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    int s, t, k, m, n, a[N], w[N];
    set< pair<int, ll> > st;
    set< pair<int, ll> > ::iterator it1, it2;
    ll f[N], ans;
    
    ll Cal(int x) {
        if (!x) return 0;
        int a = (x - 1) / k, b = x - a * k;
        return (st.lower_bound(make_pair(b, -1e18)) -> second) - 1ll * a * m;
    }
    
    void Insert(int x, ll w) {
        if (!x) x = k, w -= m;
        int a = (x - 1) / k, b = x - a * k;
        pair<int, ll> tmp = make_pair(b, w + 1ll * a * m);
        st.insert(tmp); 
        it1 = st.lower_bound(tmp);
        it2 = ++it1; --it1;
        if (it2 != st.end()) {
            if ((it2 -> second) > (it1 -> second)) return st.erase(it1), void();
        }
        while (it1 != st.begin()) {
            it2 = --it1; ++it1;
            if ((it2 -> second) < (it1 -> second)) st.erase(it2);
            else break;
        }
    }
    
    int main() {
        freopen("tourist.in", "r", stdin);
        freopen("tourist.out", "w", stdout);
        s = read(); t = read() - s; k = read();
        m = read(); n = read(); Insert(k, -m);
        for (int i = 1; i <= n; ++i) {
            int p = read() - s, w = read();
            ll tmp = Cal(p) + w;
            Insert(p, tmp); Insert(((p - 1) / k + 1) * k, tmp - m);
        }
        printf("%lld
    ", Cal(t));
        return 0;
    }
    

    B 宝石 (Unaccepted)

    题目大意 : n颗宝石,可以有D种颜色,问有多少种方案可以满足找到至少m组颜色相同的宝石,不能重复选

    • 生成函数

    Code

    Show Code

    C 线段

    题目大意 : 有n条线段,第i条连接点i和i+1,动态修改线段断不断,询问两点共有多长的时间的联通的

    • 把询问的y减1,可以转换成求x到y线段状态全是1的时刻有多少个,将每个询问x,y对应到二维平面上的一个点

    • 考虑改变第x个点的状态会对哪些询问造成影响

    • 设l,r为从x向左右延伸,全是1的极大区间的左右端点,发现左端点在[l,x],右端点在[x,r]内的点都会被影响

    • 转换到二维平面上就是左下角为(l,x),右上角为(x,r)的区间会受到影响

    • 所以,当时间为i的修改使x断开,就将受影响的区间都加上一个i,使x链接的话就给区间减去i

    • 对于时间为i个询问(x,y+1),设(x,y)点的值为ans,如果x,y之间全是1,就是ans+i,因为在连接的时候减去了个j,所以要+i,如果不全是1的话就直接是ans

    • 现在问题就转换成了在二维平面上区间加,单点查,可以kdtree,cdq,二维线段树,不过树状数组套动态开点线段树好写,跑得的也快

    • 写树状数组套动态开点线段树的话,就得变差分了,

    • 要给一个左下角为(l,x),右上角为(x,r)的区间加上w,就给(l,x)+w,(x+1,r+1)+w,(x+1,x)-w,(l,r+1)-w

    • 单点查询就要查差分数组的前缀和就好了

    Code

    Show Code
    #include <set>
    #include <cstdio>
    #define ls t[rt].l
    #define rs t[rt].r
    
    using namespace std;
    const int N = 3e5 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    char c[N];
    set<int> s;
    set<int> ::iterator it;
    int n, m, rt[N], trc;
    
    struct Tree {
        int s, l, r;
    }t[N*72];
    
    void Add(int &rt, int l, int r, int x, int w) {
        if (!rt) rt = ++trc; 
        t[rt].s += w;
        if (l == r) return;
        int mid = l + r >> 1;
        if (x <= mid) Add(ls, l, mid, x, w);
        else Add(rs, mid + 1, r, x, w);
    }
    
    void Add(int x, int y, int w) {
        for (; x <= n; x += x & -x)
            Add(rt[x], 1, n, y, w);
    }
    
    int Ask(int rt, int l, int r, int x) {
        if (r <= x) return t[rt].s;
        int mid = l + r >> 1, ans = 0;
        if (ls) ans = Ask(ls, l, mid, x);
        if (rs && x > mid) ans += Ask(rs, mid+1, r, x);
        return ans;
    }
    
    int Ask(int x, int y, int ans = 0) {
        for (; x; x -= x & -x)
            ans += Ask(rt[x], 1, n, y);
        return ans;
    }
    
    int main() {
        freopen("segment.in", "r", stdin);
        freopen("segment.out", "w", stdout);
        n = read(), m = read();
        scanf("%s", c + 1);
        s.insert(0); s.insert(++n);
        for (int i = 1; i <= n; ++i) {
            c[i] -= '0';
            if (!c[i]) s.insert(i);
        }
        for (int i = 1; i <= m; ++i) {
            char od; scanf(" %c", &od);
            int x = read();
            if (od == 't') {
                int l = x, r = x;
                it = s.lower_bound(x);
                if (*it == x) ++it; r = *it-1;
                if (*(--it) == x) --it; l = *it+1;
                if (c[x] ^= 1) {
                    s.erase(x); 
                    Add(l, x, -i), Add(x + 1, x, i);
                    Add(l, r + 1, i), Add(x + 1, r + 1, -i);
                }
                else {
                    s.insert(x);
                    Add(l, x, i), Add(x + 1, x, -i);
                    Add(l, r + 1, -i), Add(x + 1, r + 1, i);
                }
            }
            else {
                int y = read() - 1, ans = Ask(x, y);
                it = s.lower_bound(x);
                if (it != s.end() && *it <= y) printf("%d
    ", ans);
                else printf("%d
    ", ans + i);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    WebSocket connection to 'ws://192.168.3.195:9527/sockjs-node/564/fjaw2vh2/websocket' failed: Invalid frame header
    审核警告:“data-custom”太新,无法在此检查的页面上运行以及cannot declare a const variable twice 'n'解决。
    react中如何使用iconfont
    重视工作质量,对自己的代码负责
    提醒自己不要浮躁
    结果重要同样过程也同样重要,享受过程
    访问链表节点的时候,需要判断链表节点是否可以访问
    遇到问题或者线上问题不要急,冷静分析,沉着处理
    注意运算符的运算优先级别
    对每一个IO操作的返回都要进行判断
  • 原文地址:https://www.cnblogs.com/shawk/p/14577453.html
Copyright © 2011-2022 走看看