5.21pkusc模拟赛5

A.支持插入,删除rank1,删除rank last的数据结构。。set/map就可以。。我逗比地写了个treap。5.22

#include<cstdio>
#include<algorithm>
#define pa pair<int,int>
#define mp make_pair
#define N 2000005
#define inf 1<<30
using namespace std;
struct T{
    int ls,rs,sz,data,key;
}t[N];
int root;
void upd(int a){t[a].sz=t[t[a].ls].sz+t[t[a].rs].sz+1;}
int merge(int a,int b){
    if(a==0||b==0) return a+b;
    if(t[a].key<t[b].key) {t[a].rs=merge(t[a].rs,b);upd(a);return a;}
    else {t[b].ls=merge(a,t[b].ls);upd(b);return b;}
}
pa split(int a,int k){
    if(k==0) return mp(0,a);
    pa tmp;int ls=t[a].ls,rs=t[a].rs;
    if(t[ls].sz==k) {t[a].ls=0;upd(a);return mp(ls,a);}
    if(t[ls].sz==k-1) {t[a].rs=0;upd(a);return mp(a,rs);}
    if(t[ls].sz>k) {tmp=split(ls,k);t[a].ls=tmp.second;upd(a);return mp(tmp.first,a);}
    if(t[ls].sz<k-1){tmp=split(rs,k-t[ls].sz-1);t[a].rs=tmp.first;upd(a);return mp(a,tmp.second);}
}
int getmin(int k){
    while(t[k].ls) k=t[k].ls;
    return k;
}
int getmax(int k){
    while(t[k].rs) k=t[k].rs;
    return k;
}
int Rank(int x,int k){
    int tmp=inf,ans=0;  
    while(k){
        if(t[k].data==x) tmp=min(tmp,ans+t[t[k].ls].sz+1);
        if(t[k].data<x) {ans+=+t[t[k].ls].sz+1;k=t[k].rs;}
        else k=t[k].ls; 
    }
    return tmp==inf?ans:tmp;
}
void ins(int no,int x){
    int k=Rank(x,root);
    t[no].data=x;
    t[no].key=rand();
    t[no].sz=1;t[no].ls=t[no].rs=0;
    pa tmp=split(root,k);
    root=merge(tmp.first,no);
    root=merge(root,tmp.second);
}
void del(int x){
    int k=Rank(x,root);
    pa tmp1=split(root,k);
    pa tmp2=split(tmp1.first,k-1);
    root=merge(tmp2.first,tmp1.second);
}
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int o;
    while(scanf("%d",&o)&&o){
        int x,y;
        if(o==1) scanf("%d%d",&x,&y),ins(x,y);
        if(o==2) {
            int kk=getmax(root);
            printf("%d\n",kk);
            if(t[kk].data) del(t[kk].data);
        }
        if(o==3) {
            int kk=getmin(root);
            printf("%d\n",kk);
            if(t[kk].data) del(t[kk].data);
        }
    }
    return 0;
}


 
 

B.数独。。码农题略。。

C.最小表示法 5.22

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int T;
char s[20005];
int MinR(){
    int l=strlen(s+1);
    for(int i=l+1;i<=l+l;i++) s[i]=s[i-l];
    int i=1,j=2,k;
    while(i<=l&&j<=l){
        k=0;
        while(s[i+k]==s[j+k]&&k<l) k++;
        if(k==l) return min(i,j);
        if(s[i+k]>s[j+k]) 
            if(i+k+1>j) i=i+k+1;
            else i=j+1;
        else
            if(j+k+1>i) j=j+k+1;
            else j=i+1;
    }
    if(i<=l) return i;
    else return j;
}
int main(){
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%s",s+1);
        printf("%d\n",MinR());
    }
    return 0;
}
E.k小数。。略 5.22

F.有一个大小为c的容器,要求现在放b个数,使得从1-b的状态每个状态容器中都存在a[b] (a[b]<n),问最少弹出去的次数。(c<=10000,c<=n<=100000,b<=100000) 5.22

贪心,nxt[i]记录下一个为a[i]的位置,每次弹出nxt最大的。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define N 100005
using namespace std;
struct node{
    int Next,Val;
    bool operator < (const node &now)const{
        return now.Next>Next;
    }
};
int a[N],nxt[N],last[N],ans,c,n,b;
priority_queue<node>q;
bool inq[N];
void init(){
    memset(nxt,127,sizeof(nxt));
    memset(last,127,sizeof(last));
    memset(inq,0,sizeof(inq));
    ans=0;
    while(!q.empty())q.pop();
}
void solve(){
    for(int i=b;i;i--){
        nxt[i]=last[a[i]];
        last[a[i]]=i;
    }
    int sz=0,i=1;
    for(;i<=b;){
        if(!inq[a[i]]){
            q.push((node){nxt[i],a[i]});
            inq[a[i]]=1;sz++;ans++;
        }
        else q.push((node){nxt[i],a[i]});
        i++;
        if(sz==c) break;
    }
    //while(!q.empty()) printf("%d %d\n",q.top().Next,q.top().Val);
    for(;i<=b;i++){
        if(!inq[a[i]]){
            int v=q.top().Val;q.pop();
            while(!inq[v]) {v=q.top().Val;q.pop();}
            inq[v]=0;
            q.push((node){nxt[i],a[i]});
            inq[a[i]]=1;ans++;
        }
        else
            q.push((node){nxt[i],a[i]});
    }
    printf("%d\n",ans);
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    while(~scanf("%d%d%d",&c,&n,&b)){
        init();
        for(int i=1;i<=b;i++) scanf("%d",&a[i]);
        solve();
    }
    return 0;
}


发布了87 篇原创文章 · 获赞 7 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/yxr0105/article/details/51481727