清北刷题冲刺 11-03 a.m

纸牌

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 300010
int n,a[maxn],b[maxn],w[maxn],num,h[maxn],cnt;
int qread(){
    int i=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0')i=i*10+ch-'0',ch=getchar();
    return i;
}
struct node{
    int x,y;
}q[maxn];
int find(int x){
    int l=1,r=cnt,res;
    while(l<=r){
        int mid=(l+r)>>1;
        if(h[mid]<=x)res=mid,l=mid+1;
        else r=mid-1;
    }
    return res;
}
bool cmp(node u,node v){return u.x>v.x;}
int main(){
    freopen("card.in","r",stdin);freopen("card.out","w",stdout);
//    freopen("Cola.txt","r",stdin);
    n=qread();
    int limit=(n+1)/2;
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i],&b[i]);
        w[++num]=a[i];
        w[++num]=b[i];
    }
    sort(w+1,w+num+1);
    h[++cnt]=w[1];
    for(int i=2;i<=num;i++)
        if(w[i]!=w[i-1])h[++cnt]=w[i];
    for(int i=1;i<=n;i++){
        int pos1=find(a[i]);
        int pos2=find(b[i]);
        q[pos1].x++;
        q[pos2].y++;
    }
    sort(q+1,q+cnt+1,cmp);
    int ans=100000000;
    for(int i=1;i<=cnt;i++){
        if(q[i].x+q[i].y<limit)continue;
        else {
            ans=max(0,limit-q[i].x);
            printf("%d",ans);
            return 0;
        }
    }
    puts("Impossible");
    return 0;
}
40分 忘了纸牌正反相同的情况

后缀数组

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50010
using namespace std;
int n,m,tr[maxn<<4],cnt,b[maxn];
string ss;
struct node{
    int id,rank;
    string s;
}a[maxn];
bool cmp(node x,node y){return x.s<y.s;}
bool cmp1(node x,node y){return x.id<y.id;}
int query(int pos){
    int res=0;
    while(pos){
        res+=tr[pos];
        pos-=pos&-pos;
    }
    return res;
}
void add(int pos){
    while(pos<=n){
        tr[pos]+=1;
        pos+=pos&-pos;
    }
}
int main(){
//    freopen("sort.in","r",stdin);freopen("sort.out","w",stdout);
//    freopen("Cola.txt","r",stdin);
    scanf("%d%d",&n,&m);
    cin>>ss;
    for(int i=1;i<=n;i++){
        a[i].s=ss.substr(i-1,min(m,n-i+1));
        a[i].id=i;
    }
    sort(a+1,a+n+1,cmp);
    a[1].rank=++cnt;
    for(int i=2;i<=n;i++){
        if(a[i].s!=a[i-1].s)
            a[i].rank=++cnt;
        else a[i].rank=a[i-1].rank;
    }
    sort(a+1,a+n+1,cmp1);
    long long ans=0;
    for(int i=1;i<=n;i++){
        ans+=query(n)-query(a[i].rank);
        add(a[i].rank);
    }
    cout<<ans;
}
30分 树状数组,忘了字符串相等的情况

巧克力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 11
using namespace std;
int T,n,m,k,w[maxn][maxn],a[20],p[1000],cnt,b[20],c[20];
int qian[maxn];
bool flag,vis[1001];//是否wij=1; 
int work1(){
    for(int i=1;i<=k;i++){
        for(int j=1;j<=cnt;j++){
            while(a[i]%p[j]==0)a[i]/=p[j];
            if(p[j]>n&&p[j]>m)return 0;
            if(a[i]==1)break;
        }
    }
    return 1;
}
void prepare(){
    for(int i=2;i<=1000;i++){
        if(!vis[i])vis[i]=1,p[++cnt]=i;
        for(int j=1;j<=cnt&&i*p[j]<=1000;j++){
            vis[i*p[j]]=1;
            if(i%p[j]==0)break;
        }
    }
}
int count(int sta){
    int res=0;
    while(sta){
        if(sta&1)res++;
        sta>>=1;
    }
    return res;
}
int main(){
    freopen("chocolate.in","r",stdin);freopen("chocolate.out","w",stdout);
//    freopen("Cola.txt","r",stdin);
    scanf("%d",&T);
    prepare();
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        flag=1;
        int sum=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                scanf("%d",&w[i][j]);
                if(w[i][j]!=1)flag=0;
                sum+=w[i][j];
            }
        int s=0;
        for(int i=1;i<=k;i++){
            scanf("%d",&a[i]);
            s+=a[i];
        }
        sort(a+1,a+k+1);
        if(s!=sum){
            puts("no");
            continue;
        }
        if(flag){
            int ans=work1();
            if(ans==0)puts("no");
            else puts("yes");
            continue;
        }
        if(n==1){
            bool ok=0;
            for(int i=1;i<=m;i++)qian[i]=qian[i-1]+w[1][i];
            for(int sta=0;sta<(1<<m-1);sta++){
                if(count(sta)!=k-1)continue;
                int now=sta,pos=0;
                int tmp=0;
                while(now){
                    pos++;
                    if(now&1)b[++tmp]=pos;
                    now>>=1;
                }
                c[1]=qian[b[1]];
                for(int j=2;j<=tmp;j++){
                    c[j]=qian[b[j]]-qian[b[j-1]];
                }
                c[k]=qian[m]-qian[b[k-1]];
                sort(c+1,c+k+1);
                bool f=0;
                for(int j=1;j<=k;j++){
                    if(c[j]!=a[j])f=1;
                }
                if(f==0){
                    puts("yes");
                    ok=1;
                    break;
                }
            }
            if(ok==0)puts("no");
            continue;
        }
        puts("yes");
    }
}
20分 暴力
预计得分100+80+50
实际得分40+30+20
今天的题有很多坑,T1T2都掉坑里了,T3骗分策略有误
这次考试出了很多失误,以后一定要把情况考虑全面
小结
原文地址:https://www.cnblogs.com/thmyl/p/7776841.html