zoukankan      html  css  js  c++  java
  • 20200215题解

    OJ 1098

    贪心,在遇到检查点的时候保留最大的v个元素即可,用优先队列进行优化。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = ((ans << 1) + (ans << 3) + (ch ^ 48)), ch = getchar();
        while(ch >= '0' && ch <= '9');
        return ans * f;
    }
    
    const int MAXN = 200001;
    int a[MAXN], op[MAXN];
    priority_queue<int, vector<int>, greater<int> > q;
    
    int main(){
        int n = read();
        for(int i=1; i<=n; i++)
            op[i] = (getchar() == 'e'), a[i] = read();
        for(int i=1; i<=n-1; i++){
            if(!op[i]) q.push(a[i]);
            else while(q.size() >= a[i])
                q.pop();
        }
        if(q.size() < a[n]){
            printf("-1");
            return 0;
        }
        int ans = 0;
        while(!q.empty())
            ans += q.top(), q.pop();
        printf("%d", ans);
        return 0;
    }
    View Code

    OJ 1099

    对任意的两条横着的边计算竖着的边的交点,最后取组合,这是$O(n^3)$算法,将一维转为线段树(树状数组)可以达到$O(n^2logn)$

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = ((ans << 1) + (ans << 3) + (ch ^ 48)), ch = getchar();
        while(ch >= '0' && ch <= '9');
        return ans * f;
    }
    
    const int MAXN = 200001, SIZE = MAXN * 6;
    struct line{
        int posY, posX, end;
        const bool operator < (const line &x)const{
            if(posY != x.posY) return posY < x.posY;
            return posX < x.posX;
        }
    }column[MAXN], row[MAXN];
    int cntC = 0, cntR = 0;
    int hash[MAXN*6];
    
    struct point{
        int y, x, val;
        const bool operator < (const point &a)const{
            if(y != a.y) return y > a.y;
            return x > a.x;
        }
    };
    priority_queue<point> q; 
    
    int seg[SIZE + 1];
    
    inline void add(int x,int val){
        for(int i=x; i<=SIZE; i+=i&(-i))
            seg[i] += val;
    }
    
    inline int ask(int x){
        int ans = 0;
        for(int i=x; i; i-=i&(-i))
            ans += seg[i];
        return ans;
    }
    
    inline int query(int l,int r){
        return ask(r) - ask(l-1);
    }
    
    inline int ord(int val){
        return lower_bound(hash + 1, hash + 1 + hash[0], val) - hash;
    }
    
    int main(){
        int n = read();
        for(int i=1; i<=n; i++){
            int y1 = read(), x1 = read(), y2 = read(), x2 = read();
            if(x1 > x2) swap(x1, x2);
            if(y1 > y2) swap(y1, y2);
            hash[++hash[0]] = x1, hash[++hash[0]] = x2;
            hash[++hash[0]] = y1, hash[++hash[0]] = y2;
            if(x1 == x2) column[++cntC] = (line){y1, x1, y2};
            else if(y1 == y2) row[++cntR] = (line){y1, x1, x2};
        }
        sort(hash + 1, hash + 1 + hash[0]);
        hash[0] = unique(hash + 1, hash + 1 + hash[0]) - hash - 1;
        for(int i=1; i<=cntC; i++)
            column[i].posX = ord(column[i].posX), column[i].posY = ord(column[i].posY), column[i].end = ord(column[i].end);
        for(int i=1; i<=cntR; i++)
            row[i].posX = ord(row[i].posX), row[i].posY = ord(row[i].posY), row[i].end = ord(row[i].end);
        sort(column + 1, column + 1 + cntC);
        sort(row + 1, row + 1 + cntR);
        long long ans = 0;
        for(int i=1; i<=cntR; i++){
            for(int j=1; j<=cntC; j++)
                if(column[j].posX >= row[i].posX && column[j].posX <= row[i].end && column[j].posY <= row[i].posY && column[j].end >= row[i].posY)
                    q.push((point){column[j].posY, column[j].posX, 1}), q.push((point){column[j].end + 1, column[j].posX, -1});
            for(int j=i+1; j<=cntR; j++){
                while(!q.empty() && q.top().y <= row[j].posY)
                    add(q.top().x, q.top().val), q.pop();
                int cnt = query(row[j].posX, row[j].end);
                ans += cnt * (cnt - 1) / 2; 
            }
            while(!q.empty())
                add(q.top().x, q.top().val), q.pop();
        }
        printf("%lld", ans);
        return 0;
    }
    View Code

    OJ 1100

    容斥定理(莫比乌斯反演),将$gcd==d$转化为$d|gcd$之后根据a数组的情况进行组合即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = ((ans << 1) + (ans << 3) + (ch ^ 48)), ch = getchar();
        while(ch >= '0' && ch <= '9');
        return ans * f;
    }
    
    const int MAXN = 300001, MOD = 1000000007;
    int mu[MAXN], prime[MAXN >> 3];
    bool isPrime[MAXN];
    int num[MAXN], cnt[MAXN], F[MAXN];
    int fac[MAXN], inv[MAXN];
    
    void euler(int n){
        memset(isPrime, true, sizeof(isPrime));
        mu[1] = 1;
        for(int i=2; i<=n; i++){
            if(isPrime[i]){
                prime[++prime[0]] = i;
                mu[i] = -1;
            }
            for(int j=1; j<=prime[0]; j++){
                if(i * prime[j] > n)
                    break;
                isPrime[i * prime[j]] = false;
                if(i % prime[j] == 0){
                    mu[i * prime[j]] = 0;
                    break;
                }
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
    
    inline int pow(int a,int p){
        int ans = 1;
        while(p){
            if(p & 1) ans = (long long)ans * a % MOD;
            a = (long long)a * a % MOD, p >>= 1;
        }
        return ans;
    }
    
    inline int C(int n,int m){
        return (long long)fac[n] * inv[m] % MOD * inv[n-m] % MOD;
    }
    
    int main(){
        int n = read(), m = read(), k = read();
        euler(m);
        for(int i=1; i<=n; i++)
            num[read()]++;
        fac[0] = 1;
        for(int i=1; i<=n; i++)
            fac[i] = (long long)fac[i-1] * i % MOD;
        inv[n] = pow(fac[n], MOD-2);
        for(int i=n-1; i>=0; i--)
            inv[i] = (long long)inv[i+1] * (i+1) % MOD;
        for(int i=1; i<=m; i++)
            for(int j=i; j<=m; j+=i)
                cnt[i] += num[j];
        for(int i=1; i<=m; i++)
            F[i] = (cnt[i] < n-k) ? 0 : (long long)C(cnt[i], n-k) * pow(m/i-1, cnt[i]-(n-k)) % MOD * pow(m/i, n-cnt[i]) % MOD;
        for(int i=1; i<=m; i++){
            int ans = 0;
            for(int j=i; j<=m; j+=i)
                if(mu[j/i])
                    ans = ((long long)mu[j/i] * F[j] % MOD + ans + MOD) % MOD;
            printf("%d", ans);
            if(i != m) putchar(' ');
        }
        return 0;
    }
    View Code

    OJ 1414

    两个可持久化树,一个可持久化并查集,一个可持久化线段树,相当于要写两遍代码,但由于第一个可持久化并查集只有最后才有查询,所以可以离线操作,省时间复杂度又省空间复杂度,第二个只能强行线段树了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <utility>
    using namespace std;
    
    inline long long read(){
        long long ans = 0, f = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
            f *= (ch == '-') ? -1 : 1, ch = getchar();
        do ans = ((ans << 1) + (ans << 3) + (ch ^ 48)), ch = getchar();
        while(ch >= '0' && ch <= '9');
        return ans * f;
    }
    
    int n, m, size;
    const int MAXN = 200001;
    struct Segment{
        struct Node{
            int sum, son[2];
        }node[MAXN << 5];
        int head[MAXN], nodeNum;
        void build(int &x,int l = 1,int r = size){
            x = ++nodeNum;
            if(l == r) return;
            int mid = (l + r) >> 1;
            build(node[x].son[0], l, mid);
            build(node[x].son[1], mid+1, r);
        }
        void update(int &x,int pos,int l = 1,int r = size){
            node[++nodeNum] = node[x];
            x = nodeNum;
            node[x].sum++;
            if(l == r) return;
            int mid = (l + r) >> 1;
            if(pos <= mid) update(node[x].son[0], pos, l, mid);
            else update(node[x].son[1], pos, mid+1, r);
        }
        int query(int u,int v,int k,int l = 1,int r = size){
            if(l == r) return l;
            int x = node[node[v].son[0]].sum - node[node[u].son[0]].sum, mid = (l + r) >> 1;
            if(x >= k) return query(node[u].son[0], node[v].son[0], k, l, mid);
            else return query(node[u].son[1], node[v].son[1], k-x, mid+1, r);
        }
    }T;
    
    int op[MAXN], a[MAXN], b[MAXN];
    int val[MAXN], fa[MAXN];
    
    inline int get(int x){
        if(fa[x] == x) return x;
        return fa[x] = get(fa[x]);
    }
    
    int main(){
        n = read(), m = read();
        for(int i=1; i<=n; i++)
            val[i] = read(), fa[i] = i;
        for(int i=1; i<=m; i++){
            op[i] = read();
            if(op[i] == 1) a[i] = read(), b[i] = read();
            else a[i] = read();
        }
        int p = m;
        while(p){
            if(op[p] == 1){
                fa[get(a[p])] = get(b[p]);
                p--;
            }
            else p = a[p];
        }
        int u = read(), q = read();
        for(int i=1; i<=n; i++)
            if(get(u) == get(i))
                a[++a[0]] = val[i];
        for(int i=1; i<=a[0]; i++)
            b[i] = a[i];
        sort(b+1, b+1+a[0]);
        size = unique(b+1, b+1+a[0]) - b - 1;
        for(int i=1; i<=a[0]; i++)
            a[i] = lower_bound(b+1, b+1+size, a[i]) - b;
        T.build(T.head[0]);
        for(int i=1; i<=n; i++){
            T.head[i] = T.head[i-1];
            T.update(T.head[i], a[i]);
        }
        for(int i=1; i<=q; i++){
            int l = read(), r = read(), k = read();
            printf("%d
    ", b[T.query(T.head[l-1], T.head[r], k)]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jQuery实现button按钮提交表单
    jQuery实现button按钮提交表单
    egret清除缓存的方法
    jquery 路径动画贝塞尔动画
    html5自动横屏的方法
    vm虚拟机安装linux centos教程
    php pdo mysql存入转义
    格式工厂转化成mp4 avc格式 暴风影音不能播放的解决方法
    PHP过滤换行的方法
    css3 svg路径蒙版动画
  • 原文地址:https://www.cnblogs.com/PHDHD/p/12312424.html
Copyright © 2011-2022 走看看