zoukankan      html  css  js  c++  java
  • 平时十三测

    今天是真NOIP难度的题

    第一题:单调栈原题,但被读优卡成了30,以后一定要注意读入问题

    #include<bits/stdc++.h>
    using  namespace std;
    const int M = 2005;
    int a[M][M], up[M][M];
    struct node{int w, h;}q[M];
    int read(){
        int x = 0; int f = 1; char c = getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        return x*=f;
    }
    
    int main(){
        //freopen("cc.in","r",stdin);
        freopen("inspect.in","r",stdin);
        freopen("inspect.out","w",stdout);
        int n, m, ans = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)a[i][j] = read();
        for(int i = n; i; i--)
            for(int j = 1; j <= m; j++)
                up[i][j] = a[i][j] ? up[i+1][j] + 1 : 0;
        for(int st = 1; st <= n; st++){
            int h = 1, t = 1;
            q[1].w = 1, q[1].h = up[st][1];
            for(int i = 2; i <= m; i++){
                int w = 0;
                while(h <= t && up[st][i] <= q[t].h){
                    w += q[t].w;
                    ans = max(ans, min(w, q[t].h));
                    t--;
                }
                q[++t] = (node) {1 + w, up[st][i]};
            }
            int w = 0;
            while(h <= t){
                w += q[t].w;
                ans = max(ans, min(w, q[t].h));
                t--;
            }        
        }
        
        printf("%d
    ", ans);
    } 
    View Code

    第二题:开始想贪心,看到数据觉得可能不是,然后感觉好像方格取数加强版,就上了一波费用流,其实就是最基本的最小链覆盖;

    但是后来有人贪心过了,把x排序以后不就变成了导弹拦截。。。

    #include<bits/stdc++.h>
    using  namespace std;
    const int N = 705, M = 3e5, inf = 1e9;
    int tot = 1, S, T, SS;
    int h[N], dis[N], px[N], py[N], pre[N], pree[N], n;
    bool inq[N];
    struct zz{int x,y;}qq[N];
    bool cmp(zz A, zz B){return A.x == B.x ? A.y < B.y : A.x < B.x;}
    struct edge{int v, nxt, w, pf, f;}G[M];
    void add(int u, int v, int f, int w){
        G[++tot].v = v, G[tot].nxt = h[u], G[tot].w = w, G[tot].pf = G[tot].f = f, h[u] = tot;
        G[++tot].v = u, G[tot].nxt = h[v], G[tot].w = -w, G[tot].pf = G[tot].f = 0, h[v] = tot;
    }
    #define RG register
    queue <int> q;
    bool spfa(){
        memset(dis, 0x8f, sizeof(dis));
        memset(pre, 0, sizeof(pre));
        memset(pree, 0, sizeof(pree));
        dis[SS] = 0, inq[SS] = 1;
        q.push(SS);
        while(!q.empty()){
            int u=q.front();q.pop();inq[u]=0;
            for(RG int i = h[u]; i; i = G[i].nxt){
                int v = G[i].v;
                if(G[i].f && dis[v] < dis[u] + G[i].w){
                    dis[v] = dis[u] + G[i].w;
                    pre[v] = u, pree[v] = i;
                    if(!inq[v])q.push(v), inq[v] = 1;
                    //fprintf(stderr, "%d %d %d %d %d
    ", u, v, dis[u], dis[v], G[i].w);
                }
            }
        }
        return dis[T] > 0;
    }
    
    
    int check(int k){
        G[tot].f = 0, G[tot^1].f = k;
        int ret = 0;
        for(int i = 1; i <= tot - 2; i++)G[i].f = G[i].pf;
        while(spfa()){
            int u = T, del = inf;
            while(u != SS){
                del = min(del, G[pree[u]].f);
                u = pre[u];
            }
            u = T;
            while(u != SS){
                G[pree[u]].f -= del;
                G[pree[u]^1].f += del;
                u = pre[u];
            }
            ret += dis[T]*del;
        }
        return ret;
    }
    
    int main(){
        //freopen("cc.in","r",stdin);
        freopen("militarytraining.in","r",stdin);
        freopen("militarytraining.out","w",stdout);
        scanf("%d", &n);
        S = 0, T = 2 * n + 1, SS = T + 1;
        for(int i = 1; i <= n; i++)
            scanf("%d%d", &qq[i].x, &qq[i].y);
        sort(qq + 1, qq + 1 + n, cmp);
        int cnt = 0;
        for(RG int i = 1; i <= n; i++)
            if(qq[i].x == qq[i-1].x && qq[i].y == qq[i-1].y)continue;
            else px[++cnt] = qq[i].x, py[cnt] = qq[i].y;
        for(RG int i = 1; i <= cnt; i++)
            for(RG int j = 1; j <= cnt; j++)
                if(i != j && px[i] <= px[j] && py[i] <= py[j])
                    add(i + n, j, inf, 0);
        for(RG int i = 1; i <= cnt; i++){
            add(S, i, 1, 0);
            add(i + n, T, 1, 0);
            add(i, i + n, 1, 1);
        }
        add(SS, S, 0, 0);
        int lf = 1, rg = cnt, ans = 0;
        while(lf <= rg){
            int mid = (lf + rg) >> 1;
            if(check(mid) == cnt) ans = mid, rg = mid - 1;
            else lf = mid + 1;
        }    
        printf("%d
    ", ans);
    }
    View Code

    第三题:思维好题

    考虑将询问按左端点排序,从右向左做。
    维护一个数组t,t[i]表示如果询问区间包含了点i,答案会增加t[i](可能为负)。
    初始情况下t全为0,i从n枚举到1,对某个i,考虑a[i]这个数在i位置及其以后是否出现过a[i]次及以上,假设a[i]在位置x出现了第a[i]次,在位置y出现了第a[i]+1次,即表示对于左端点为i的询问区间,当右端点在[x,y)时,a[i]会贡献1的答案,否则贡献0的答案,此时设t[x]=1且t[y]=-1即可。
    用一个树状数组维护t数组,可以很容易的统计前缀和。
    复杂度为O(nlogn+qlogn+qlogq)。

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e6 + 5;
    int lst[M], a[M], n, c[M], ans[M], cnt[M], que[M], gx[M];
    vector <int> vec[M];
    #define RG register
    struct node{int l, r, id;}q[M];
    bool cmp(node A, node B){
        return A.l < B.l;
    }
    
    int read(){
        int x = 0; int f = 1; char c = getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        return x*=f;
    }
    void add(int x, int d){
        for(; x <= n; x += x&(-x))
            c[x] += d;
    }
    int query(int x){
        int ret = 0;
        for(; x; x -= x&(-x))
            ret += c[x];
        return ret;
    }
    int main(){
        freopen("count.in","r",stdin);
        freopen("count.out","w",stdout);
        n = read();int Q = read(), tot = 0;
        for(RG int i = 1; i <= n; i++){
            a[i] = read();
            cnt[a[i]]++;
            vec[a[i]].push_back(i);
        }
        for(RG int i = 1; i <= n; i++)
            if(cnt[i] >= i)que[++tot] = i, gx[i] = 1;
        for(RG int i = 1; i <= tot; i++){
            int u = que[i];
            if(vec[u].size() == u) add(vec[u][u-1], 1);
            else {
                add(vec[u][u-1], 1);
                add(vec[u][u], -1);
            }
            lst[u] = u;
        }
        for(RG int i = 1; i <= Q; i++)
            q[i].l = read(), q[i].r = read(), q[i].id = i;
        sort(q + 1, q + 1 + Q, cmp);
        
        int lf = 0;
        for(RG int i = 1; i <= Q; i++){
            while(lf < q[i].l){
                lf++;
                int u = a[lf-1];
                if(!gx[u])continue;
                if(lst[u] == (int)vec[u].size()){
                    add(vec[u][lst[u]-1], -1);
                    lst[u]++;
                }
                else if(lst[u] == (int)vec[u].size()-1){
                    add(vec[u][lst[u]-1], -1);
                    add(vec[u][lst[u]], 2);
                    lst[u]++;
                }
                else if(lst[u] <= (int)vec[u].size()-2){
                    add(vec[u][lst[u]-1], -1);
                    add(vec[u][lst[u]], 2);
                    add(vec[u][lst[u]+1], -1);
                    lst[u]++;
                }
            
            }
            
            ans[q[i].id] = query(q[i].r);
        }
        for(int i = 1; i <= Q; i++)printf("%d
    ", ans[i]);
    }
    View Code
  • 相关阅读:
    hadoop配置笔记
    hadoop安装笔记
    抄一篇maven的备忘
    这个计划任务的名字老记不住,还是存一下了
    GodMode
    恢复oracle数据从delete
    在注册表中查看Windows10系统激活密钥的方法
    Jenkins 提效工具之 Jenkins Helper 使用介绍
    移动硬盘安装Ubuntu系统(UEFI引导)的一些记录
    Linux系统下的Jenkins的简要安装方法
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9831236.html
Copyright © 2011-2022 走看看