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;
}