HGOI2010816 (NOIP 提高组模拟赛 day1)

Day1 210pts(含T1莫名的-10pts和T3莫名的-30pts)

100+70+40=210

rank 29

 

这道题第一眼看是字符串匹配问题什么KMP啊,又想KMP不会做啊,那就RK Hash 吧,结果Hash打了一半发现Hint:要全排列,

然后掐指一算3000!一定爆所以换思路,对于区间[l,r]字符种类和对应数目与前面那个串完全相同就是一个匹配,常数是52,应该能过

# include <bits/stdc++.h>
using namespace std;
char a[3005],b[3000005];
int sta[120],stb[120],lena,lenb;
int fun(char ch)
{
    if ('A'<=ch&&ch<='Z') return ch-'A'+1;
    else return ch-'a'+1+26;
}
bool check()
{
    for (int i=1;i<=52;i++)
      if (sta[i]!=stb[i]) return false;
    return true;
}
int main()
{
    freopen("mayan.in","r",stdin);
    freopen("mayan.out","w",stdout);
    int t1,t2; scanf("%d%d",&t1,&t2);
    getchar();
    for (int i=1;i<=t1;i++) a[i]=getchar(); getchar();lena=t1;
    for (int i=1;i<=t2;i++) b[i]=getchar(); getchar();lenb=t2;
    for (int i=1;i<=lena;i++) {sta[fun(a[i])]++;}
    int ans=0;
    for (int i=1;i<=lenb;i++) {
        if (i<=lena-1) { stb[fun(b[i])]++;continue;} 
        else if (i==lena) { 
            stb[fun(b[i])]++;
            if (check()) ans++;
            continue;
        }
        stb[fun(b[i-lena])]--; stb[fun(b[i])]++;
        if (check()) ans++;
    }
    printf("%d\n",ans);
    return 0;
}

事情是这样的,求形如(a...a)(b....b)或(a.....a)的子序列个数

如abba中{a,b,ab,bb,ba,abb,bba}有且有7个

于是考场上写出20行的STL代码,70分!跟我一起念:STL大法好qwq

70pts(MLE/TLE)

# include <bits/stdc++.h>
using namespace std;
set<string>stt; string s;
int main()
{
    freopen("strange.in","r",stdin); 
    freopen("strange.out","w",stdout);
    cin>>s; 
    int len=s.length();
    char ch1,ch2;
    for (int i=0;i<len;i++) {
        ch1=s[i]; int j=i; 
        while (j<len&&s[j]==ch1) { j++; stt.insert(s.substr(i,j-i));}
        ch2=s[j];
        while (j<len&&s[j]==ch2) { j++; stt.insert(s.substr(i,j-i));}
    }    
    int ans=0,i;
    printf("%d\n",stt.size()); 
    return 0;
}

好了讲正解,vector[i][j]表示形如(i....i)(j....j)的二元组(x,y)表示有x个i,y个j组成,然后就会对于每个vecort都会有二元组,然后面积求和即可

然后把所有面积的并集求出来就是vector[i][j]的值,然后把各值求出来累加就行了。

# include <bits/stdc++.h>
using namespace std;
struct Node{
    int x,y;
};
vector <Node> a[27][27];
Node m[200005];
int n;
bool cmp(Node aa,Node bb)
{
    if (aa.x!=bb.x) return aa.x>bb.x;
    else return aa.y>bb.y;
}
char s[200005];
int fun()
{
    sort(m+1,m+1+n,cmp);
    int X=m[1].x,Y=m[1].y;
    int S=X*Y;
    for (int i=2;i<=n;i++) 
     if (m[i].y>Y) {
         S=S+(m[i].y-Y)*m[i].x;
         X=m[i].x;Y=m[i].y;
     }
     return S;
}
int main()
{
    scanf("%s",s+1); 
    int len=strlen(s+1);
    int i;
    for (i=1;i<=len;i++) {
        char ch1,ch2;
        int cnt1=0,cnt2=0;
        ch1=s[i];  int j=i;
        while (j<=len&&s[j]==ch1) j++,cnt1++;
        if (j>len) j=len; ch2=s[j];
        int kk=j-1;
        while (j<=len&&s[j]==ch2) j++,cnt2++;
        if (ch1==ch2) continue;
        Node N; N.x=cnt1; N.y=cnt2;
        a[ch1-'a'+1][ch2-'a'+1].push_back(N);
        i=kk;
    }
    int ans=0;
    for (int i=1;i<=26;i++)
     for (int j=1;j<=26;j++)
      {
          n=(int)(a[i][j].size());
          memset(m,0,sizeof(m));
        for (int k=1;k<=n;k++) m[k]=a[i][j][k-1];
          ans=ans+fun();
     }
     for (int i=1;i<=26;i++) {
         int cnt=0,maxx=0;
         bool flag=false;
         for (int j=1;j<=len;j++) if (s[j]==i+'a'-1) flag=true;
         for (int j=1;j<=len;j++) {
             while (s[j]==i+'a'-1&&s[j+1]==i+'a'-1&&j<len) j++,cnt++;
             maxx=max(maxx,cnt);
             cnt=0; 
         }
        if (flag)ans=ans+maxx+1; 
     } 
      printf("%d\n",ans);
    return 0;
}

std:

#include <bits/stdc++.h>
using namespace std;
template <typename T> void read(T &t) {
    char ch=getchar(); int f=1; t=0;
    while ('0'>ch||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
    do { (t*=10)+=ch-'0'; ch=getchar(); } while ('0'<=ch&&ch<='9'); t*=f;
}
typedef long long ll;
const int maxn=100010;
int n,k,x[maxn],a[maxn],sz;
map<int,int> m;
ll ans;
int main() {
    read(n); read(k);
    for (int i=1;i<=n;i++) {
        read(x[i]); m[x[i]]++;
    }
    sort(x+1,x+(n+1));
    for (int i=1;i<=n;i++)
        if (x[i]!=x[i-1]) a[++sz]=x[i];
    int pos=0,c1=0,c2=0;
    for (int i=1;i<=sz;i++) {
        while (pos<sz&&a[pos+1]<=(ll)a[i]*k) {
            pos++;
            if (m[a[pos]]>=2) c1++;
            else c2++;
        }
        int v=0;
        if (m[a[i]]>=2) v++;
        int s=c1+c2-1;
        ans+=3*(c1-v);
        if (s>1) ans+=3LL*s*(s-1);
        if (m[a[i]]>=2) ans+=3*(c1+c2-1);
        if (m[a[i]]>=3) ans++;
        if (m[a[i]]>=2) c1--; else c2--;
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2018-08-16 16:56  ljc20020730  阅读(171)  评论(0编辑  收藏  举报