0811 鍾 區間第K大(kth)

大模擬,這真是沒什麼好說的,一個一個時間往後走就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000005
using namespace std;
int col,n,sz;
int f[105][105],a[maxn],c[maxn];
int pre[maxn],nex[maxn],sum[105];
bool vis[105];
inline int read()
{
      int x=0,op=1;;
      char ch=getchar();
      if(ch=='-') op=-1;
      while(ch<'0'||ch>'9') ch=getchar();
      while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
      return x*op; 
}
inline void del(int x)
{
     nex[pre[x]]=nex[x];
     pre[nex[x]]=pre[x];  
}
int main()
{
    col=read();n=read();
    sz=col;
    for(int i=1;i<=col;i++)
      for(int j=1;j<=col;j++)  scanf("%d",&f[i][j]);
    for(int i=1;i<=n;i++){ a[i]=read(); c[i]=1; sum[a[i]]++; } 
    for(int i=0;i<=n+1;i++){ pre[i]=i-1;nex[i]=i+1;}
    int op=0;
    while(1)
    {
          int y,x;
          for(x=nex[0];x<=n;x=y){
              y=nex[x];
              if(y>n) break;
              c[x]+=f[a[x]][a[y]];
              c[y]+=f[a[y]][a[x]];
          }
          for(x=nex[0];x<=n;x=nex[x]) 
          if(c[x]<=0){
             del(x);
             sum[a[x]]--;
             if(sum[a[x]]==0) sz--;
          }
          if(sz==1) break;
    }
    printf("%d\n",a[nex[0]]);
    //while(1);
    return 0;
}
區間第k大

每次詢問有多少個區間第k大的數爲x

從每一個數往兩邊找,對每一個數記錄sum[i] ,到第i位比x大的數的個數,num[i] 有i個比x大的數的區間的個數

對於x,左邊選i個比他大的數,右邊選j個,那麼x在區間的排名就是i+j+1,統計每個數對答案的貢獻,對於相等的數,爲了防止某些區間重複計算,可以規定下標大的數比較大

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2005
using namespace std;
int n,Q;
int f[maxn][maxn],a[maxn]; 
int num1[maxn],num2[maxn],sum[maxn];
inline int read()
{
    int x=0,op=1;
    char ch=getchar();
    if(ch=='-') op=-1;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*op;   
}
void pre()
{
     int op;
     for(int i=1;i<=n;i++){
        op=a[i];
        memset(num1,0,sizeof(num1));
        memset(num2,0,sizeof(num2));
        memset(sum,0,sizeof(sum));
        sum[i]=0;num1[0]++;num2[0]++;
        for(int j=i-1;j>=1;j--){
          if(a[j]>a[i]) sum[j]=sum[j+1]+1;
          else sum[j]=sum[j+1]; 
          num1[sum[j]]++;
        }
        for(int j=i+1;j<=n;j++){
          if(a[j]>=a[i]) sum[j]=sum[j-1]+1;
          else sum[j]=sum[j-1];
          num2[sum[j]]++;
        }
        for(int i=0;i<=sum[1];i++)
          for(int j=0;j<=sum[n];j++){
           f[op][i+j+1]+=num1[i]*num2[j];
          }
     }
}
int main()
{
   // freopen("in.txt","r",stdin);
    n=read();Q=read();
    for(int i=1;i<=n;i++) a[i]=read();
    pre();
    int k,x;
    while(Q--){
       k=read();x=read();
       printf("%d\n",f[x][k]);
    }
    //while(1);
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章