zoukankan      html  css  js  c++  java
  • P4396 [AHOI2013]作业

    题目链接

    luogu4396

    思路

    唯有水题暖人心
    咕了4天,今天跟着std对拍才做出来不得不说题解真的水的一批
    先离散化一下
    第一问差分询问,权值树状数组套一套就好了 (nlog_{n})
    第二问,Emma
    莫队,加上树状数组维护修改 (nlog_{n}sqrt_{n})
    (3s)随便过吧,最慢的也才(800ms)

    代码

    #include <bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int maxn = 1e5 + 7;
    int n, m, w[maxn];
    int sub[maxn * 3], belong[maxn], lsh[maxn * 3];
    struct query {
        int s, t, a, b, id, ans1, ans2, tmp;
    } Q[maxn];
    bool cmp1(query a, query b) {return a.s < b.s;}
    bool cmp2(query a, query b) {return a.t < b.t;}
    bool cmp3(query a, query b) {return belong[a.t] == belong[b.t] ? a.s < b.s : a.t < b.t;}
    bool cmp4(query a, query b) {return a.id < b.id;}
    int read() {
        int x = 0, f = 1; char s = getchar();
        for (; s < '0' || s > '9'; s = getchar()) if (s == '-')f = -1;
        for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
        return x * f;
    }
    int sum[maxn*6];
    void add(int x, int ad) {
        for (int i = x; i <= 3e5; i += (i&-i)) sum[i] += ad;
    }
    int query(int x) {
        int ans = 0;
        for (int i = x; i >= 1; i -= (i&-i)) ans += sum[i];
        return ans;
    }
    inline void add(int x) {
        if (!sub[x]) add(x, 1);
        sub[x]++;
    }
    inline void delet(int x) {
        sub[x]--;
        if (!sub[x]) add(x, -1);
    }
    int main() {
        // read
        n = read(), m = read();
        int k = sqrt(n);
        FOR(i, 1, n) lsh[i] = w[i] = read();
        FOR(i, 1, n) belong[i] = (i - 1) / k + 1;
        int js = n;
        FOR(i, 1, m) {
            Q[i].s = read(),Q[i].t = read(),Q[i].a = read(),Q[i].b = read();
            lsh[++js] = Q[i].a,lsh[++js] = Q[i].b, Q[i].id = i;
        }
        sort(lsh + 1, lsh + 1 + n + m * 2);
        int nn = unique(lsh + 1, lsh + 1 + n + 2 * m) - (lsh + 1);
        FOR(i, 1, n) w[i] = lower_bound(lsh + 1, lsh + 1 + nn, w[i]) - lsh;
        FOR(i, 1, m) {
            Q[i].a = lower_bound(lsh + 1, lsh + 1 + nn, Q[i].a) - lsh;
            Q[i].b = lower_bound(lsh + 1, lsh + 1 + nn, Q[i].b) - lsh;
        }
        
        // work1
        js = 1;
        sort(Q + 1, Q + 1 + m, cmp1);
        FOR(i, 1, n) {
            for (; Q[js].s == i; ++js)
                Q[js].tmp = query(Q[js].b) - query(Q[js].a - 1);
            add(w[i], 1);
        }
    
        js = 1;
        sort(Q + 1, Q + 1 + m, cmp2);
        memset(sum, 0, sizeof(sum));
        FOR(i, 1, n) {
            add(w[i], 1);
            for(;Q[js].t == i;++js)
                Q[js].ans1 = query(Q[js].b) - query(Q[js].a - 1) - Q[js].tmp;
        }
        
        // work2
        sort(Q + 1, Q + 1 + m, cmp3);
        memset(sum, 0, sizeof(sum));
        int l = 1, r = 0;
        FOR(i, 1, m) {
            while (l > Q[i].s) add(w[--l]);
            while (l < Q[i].s) delet(w[l++]);
            while (r < Q[i].t) add(w[++r]);
            while (r > Q[i].t) delet(w[r--]);
            Q[i].ans2 = query(Q[i].b) - query(Q[i].a - 1);
        }
    
        //print
        sort(Q + 1, Q + 1 + m, cmp4);
        FOR(i, 1, m) printf("%d %d
    ", Q[i].ans1, Q[i].ans2);
    }
    
  • 相关阅读:
    如何找出数组中重复次数最多的数
    如何计算两个有序整型数组的交集
    如何分别使用递归与非递归实现二分查找算法
    如何用递归算法判断一个数组是否是递增
    如何用一个for循环打印出一个二维数组
    如何用递归实现数组求和
    ElasticSearch安装和head插件安装
    SpringBoot全局异常处理方式
    Redis高级命令操作大全--推荐
    Mysql中FIND_IN_SET和REPLACE函数简介
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9828461.html
Copyright © 2011-2022 走看看