• 杭电多校第二场1012 L


    这题是真的秀。。。我服了。。。线段树用好了,感觉什么都可以写。。。

    题目大意:给你一个串,问满足以下条件的子串中最长的是多长:对于每个数字,要么在这个子串没出现过,要么出现次数超过k次。

    我们对于每一个位置i,肯定希望往左找到最远满足条件的,然后维护一个最大值,岂不美哉?

    那么我们该如何找到最远满足条件的???那么又该维护一些什么东西?

    我们维护一个数组t[],t[j]=m表示从i位往左到j位置,满足条件的个数(要么为0个,要么大于等于k个),用线段树维护。

    对于每个一个位置i,我们需要在当前位置加上C-1,代表从当前点,区间长度为0

    我们每次讨论t[i]的时候就是将i位置作为右端点,因为a[i]=x,所以除x以外的其他数,左端点都可以是i位置,因为[i,i]这个区间内只有x出现了1次,其他都是出现0次,出现0次的肯定是可行的,所以先加上C-1(-1是因为i位置是否为x的可行左端点还需要进一步讨论)

    然后我们考虑从i位置的数a[i],由于第i位出现了a[i],那么造成了当前位置到上一个位置和a[i]相等值的位置,这个区间以前是可以的,但是现在变得不可以。我们需要

    从上一个位置到这个的值全部-1,代表a[i],不再这个区间可用。并且,我们从当前位置往前的k个a[i]的位置的到前k-1个a[i]的位置,这个位置以前是不可用的,但是由于右边新增加了一个a[i],这个区间将由不可用变成可用,那么在区间内部应该+1,代表这个值原来不可用,现在可用。

    #include<bits/stdc++.h>
    #define LL long long
    #define lson rt<<1
    #define rson rt<<1|1
    using namespace std;
    const int maxx = 1e5+6;
    struct node{
       int l,r;
       int laze,cnt;
    }tree[maxx<<2];
    int a[maxx];
    int pre[maxx];
    int n,c,k;
    vector<int>G[maxx];
    void push_down(int rt){
       if (tree[rt].laze){
          tree[lson].cnt+=tree[rt].laze;
          tree[rson].cnt+=tree[rt].laze;
          tree[lson].laze+=tree[rt].laze;
          tree[rson].laze+=tree[rt].laze;
          tree[rt].laze=0;
       }
    }
    void buildtree(int rt,int l,int r){
        tree[rt].l=l;
        tree[rt].r=r;
        tree[rt].laze=0;
        tree[rt].cnt=0;
        if (l==r){
            return;
        }
        int mid=(l+r)>>1;
        buildtree(lson,l,mid);
        buildtree(rson,mid+1,r);
    }
    void update(int rt,int ul,int ur,int w){
        int l=tree[rt].l;
        int r=tree[rt].r;
        if(ul<=l && r<=ur){
            tree[rt].cnt+=w;
            tree[rt].laze+=w;
            return ;
        }
        push_down(rt);
        int mid=(l+r)>>1;
        if (ur<=mid){
            update(lson,ul,ur,w);
        }else if(ul>mid){
            update(rson,ul,ur,w);
        }else {
            update(lson,ul,mid,w);
            update(rson,mid+1,ur,w);
        }
        tree[rt].cnt=max(tree[lson].cnt,tree[rson].cnt);
    }
    int query(int rt){
        int l=tree[rt].l;
        int r=tree[rt].r;
        if(l==r){
            return l;
        }
        push_down(rt);
        int mid=(l+r)>>1;
        if(tree[lson].cnt==c){
            return query(lson);
        }else if(tree[rson].cnt==c){
            return query(rson);
        }else {
            return -1;
        }
    }
    int main(){
      while(~scanf("%d%d%d",&n,&c,&k)){
          for(int i=1;i<=c;i++){
            G[i].clear();
            G[i].push_back(0);
          }
          memset(pre,0,sizeof(pre));
          for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            G[a[i]].push_back(i);
          }
          buildtree(1,1,n);
          if(k==1){
            printf("%d
    ",n);
            continue;
          }
          int ans=0;
          for (int i=1;i<=n;i++){
             int x=a[i];
             int p=++pre[a[i]];
             update(1,i,i,c-1);
             if(G[a[i]][p-1]+1<=G[a[i]][p]-1)
                update(1,G[a[i]][p-1]+1,G[a[i]][p]-1,-1);
             if(p>=k)
                update(1,G[a[i]][p-k]+1,G[a[i]][p-k+1],1);
             int pos=query(1);
             if(pos!=-1){
                ans=max(ans,i-pos+1);
             }
          }
          printf("%d
    ",ans);
      }
      return 0;
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    【结对编程收获】
    【第二次个人作业】结对作业Core第一组:四则运算生成PB16061082+PB16120517
    【第七周读书笔记】读《计算机系统详解》
    【第五周课堂作业】创新案例分析
    【第六周读书笔记】计算机体系结构读后感
    个人总结——马睿淳
    团队项目心得(6.15)
    团队项目心得
    《代码大全》读书笔记——第九周
    《我是一只IT小小鸟》(续)读书笔记——第八周
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11420399.html
Copyright © 2020-2023  润新知