A:给数组a,sort后求最长区间[l,r]使区间内max-min<=d,输出n-最长区间长度。

题解:暴力。。。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> pa;
const int N=1001;
//struct E{int to,nxt;}e[N<<1];
int n,a[N];
int Write[20],WRI;
void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;}
void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));}
//void add(LL x,LL y){e[++cnt]=(E){y,head[x]}; head[x]=cnt;}
//void Add(LL x,LL y){add(x,y); add(y,x);}
int main()
{
    //judge();
    n=read(); int d=read();
    for (int i=1;i<=n;i++) a[i]=read();
    int ans=1000000;
    sort(a+1,a+1+n);
    for (int i=1,j=1;i<=n;i++)
    {
        while (j<n&&a[j+1]-a[i]<=d) j++;
        ans=min(ans,n-(j-i+1));
    }
    printf("%d",ans);
    return 0;
}
View Code

B:有一个数x=n,可以用A的金币使x--,或在x%k==0时用B的金币使x/=k,求将它变为1的最小代价。

题解:贪心,先使x%=k,然后比较用A和B那个优,注意一些细节,没开long long爆了4发,┭┮﹏┭┮

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> pa;
//struct E{int to,nxt;}e[N<<1];
LL n,A,B,k,x;
int Write[20],WRI;
void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
LL read(){LL d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;}
void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));}
//void add(LL x,LL y){e[++cnt]=(E){y,head[x]}; head[x]=cnt;}
//void Add(LL x,LL y){add(x,y); add(y,x);}
int main()
{
    //judge();
    n=read(); k=read(); A=read(); B=read();
    if (k==1)
    {
        printf("%lld",(n-1)*A);
        return 0;
    }
    x=n;
    LL ans=0;
    while (x!=1)
    {
        if (x<k) {ans+=(x-1)*A; break;}
        ans+=x%k*A;
        x-=x%k;
        if ((x-x/k)*A>B) ans+=B; else ans+=(x-x/k)*A;
        x/=k;
    }
    printf("%lld",ans);
    return 0;
}
View Code

C:给一个字符串s,求字典序最小的字符串a,使a的长度为k,且a的字典序大于s,且a的字符集是s的子集

题解:k>n时,在原串后加上k-n个s中最小字母即可,k<=n时,用类似进制加1的方法,使最后一位变为比它大的最小字符,如果它已经是最大的,就“进位”上去。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> pa;
const int N=100010;
//struct E{int to,nxt;}e[N<<1];
int n,k,t,b[26];
char s[N],f[26];
int Write[20],WRI;
void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;}
void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));}
//void add(LL x,LL y){e[++cnt]=(E){y,head[x]}; head[x]=cnt;}
//void Add(LL x,LL y){add(x,y); add(y,x);}
int main()
{
    //judge();
    n=read(); k=read();
    scanf("%s",s+1);
    for (int i=1;i<=n;i++) b[s[i]-'a']=1;
    for (int i=0;i<26;i++)
        if (b[i])
            f[++t]=(char)(i+'a');
    if (n==k)
    {
        int x=n;
        while (s[x]==f[t]) s[x]=f[1],x--;
        for (int i=1;i<=t;i++)
            if (f[i]==s[x])
            {s[x]=f[i+1];
            break;
        }
        for (int i=1;i<=n;i++) printf("%c",s[i]);
    }
    else if (n<k)
    {
        for (int i=1;i<=n;i++) printf("%c",s[i]);
        for (int i=1;i<=k-n;i++) printf("%c",f[1]);
    }
    else
    {
        int x=k;
        while (s[x]==f[t]) s[x]=f[1],x--;
        for (int i=1;i<=t;i++)
            if (f[i]==s[x])
            {s[x]=f[i+1];
            break;
        }
        for (int i=1;i<=k;i++) printf("%c",s[i]);
    }
    return 0;
}
View Code

D:有两个数组a,b,b的生成规则如下:

b1 = b2 = b3 = b4 = 0.

For all 5 ≤ i ≤ n:

  • bi = 0 if ai, ai - 1, ai - 2, ai - 3, ai - 4 > r and bi - 1 = bi - 2 = bi - 3 = bi - 4 = 1
  • bi = 1 if ai, ai - 1, ai - 2, ai - 3, ai - 4 < l and bi - 1 = bi - 2 = bi - 3 = bi - 4 = 0
  • bi = bi - 1 otherwise

求一组满足条件的l,r

题解:直接暴力求解即可。。。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> pa;
const int N=100010;
//struct E{int to,nxt;}e[N<<1];
int n,b[N],l,r;
char a[N];
int Write[20],WRI;
void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;}
void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));}
//void add(LL x,LL y){e[++cnt]=(E){y,head[x]}; head[x]=cnt;}
//void Add(LL x,LL y){add(x,y); add(y,x);}
int main()
{
    //judge();
    n=read();
    l=-1000000000; r=1000000000;
    for (int i=1;i<=n;i++) b[i]=read();
    scanf("%s",a+1);
    for (int i=5;i<=n;i++)
        if (a[i]!=a[i-1]&&a[i-1]==a[i-2]&&a[i-2]==a[i-3]&&a[i-3]==a[i-4])
            if (a[i]=='1')
            {
                for (int j=i-4;j<=i;j++)
                    l=max(l,b[j]+1);
            }
            else
            {
                for (int j=i-4;j<=i;j++)
                    r=min(r,b[j]-1);
            }
    printf("%d %d",l,r);
    return 0;
}
View Code

E:将数组a划分成若干段,使每段的f值之和最小,其中f值是区间内元素和减去前k/c(下取整)小的数。

题解:考虑去掉2个数,也就是2c<=段长<3c时,将它拆成两段肯定不会变劣,这应该比较显然吧,然后取c肯定不会劣于c+1,那么我们在DP时只要从i-c和i-1转移过来即可,同时要维护[i-c+1,i]的最小值,我是用单调队列的。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define mp make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> pa;
const int N=100010;
//struct E{int to,nxt;}e[N<<1];
#define int LL
int n,a[N],c,q[N],h,t;
LL s[N],f[N];
int Write[20],WRI;
void judge(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;}
void write(int x){if (!x){putchar('0'); return;}if (x<0) putchar('-'),x=-x;for (WRI=1;x;x/=10,WRI++) Write[WRI]=x%10;for (int i=WRI-1;i;i--) putchar((char)(Write[i]+48));}
//void add(LL x,LL y){e[++cnt]=(E){y,head[x]}; head[x]=cnt;}
//void Add(LL x,LL y){add(x,y); add(y,x);}
signed main()
{
    //judge();
    n=read(); c=read();
    for (int i=1;i<=n;i++) a[i]=read(),s[i]=s[i-1]+a[i];
    h=1;
    for (int i=1;i<=n;i++)
    {
        f[i]=f[i-1]+a[i];
        while (h<=t&&q[h]<i-c+1) h++;
        while (h<=t&&a[q[t]]>a[i]) t--;
        q[++t]=i;
        //for (int j=h;j<=t;j++) printf("%d ",q[j]); puts("");
        if (i>=c) f[i]=min(f[i],f[i-c]+s[i]-s[i-c]-a[q[h]]);
    }
    printf("%lld",f[n]);
    return 0;
}
View Code

F:给数组a,有两种操作,1 l r查询[l,r]中每个数出现次数的mex,注意是出现次数,mex是最小未出现的自然数,2 x y将a[x]修改为y。

题解:带修改莫队可以解决此题。带修改莫队不会的同学可以先去做下BZOJ2120,然后mex+莫队可以参考BZOJ3585。带修改莫队就是加入了第三关键字time,然后按(左端点所在块,右端点所在块,时间)排序,其中时间指的是在第几次修改操作后。注意修改时要记下原来的数,以便还原回去。维护mex可以对权值分块,如果某块中数的个数==R-L+1,那么这块所有数都出现了,否则暴力扫,我有个同学直接暴力维护也过了。。。

#include<cstdio>
#include<cmath>
#include<map>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=200010;
struct node{int l,r,id,ans,tim;}q[N];
struct nodee{int x,y,z;}b[N];
int n,m,pos[N],L[N],R[N],a[N],qn,f[N],h[N],g[N],l,r,cnt,c[N];
int read(){int d=0,f=1; char c=getchar(); while (c<'0'||c>'9'){if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=d*10+c-48,c=getchar(); return d*f;}
bool cmp1(node a,node b){return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&pos[a.r]<pos[b.r]||pos[a.l]==pos[b.l]&&pos[a.r]==pos[b.r]&&a.tim<b.tim;}
bool cmp2(node a,node b){return a.id<b.id;}
void add(int x)
{
    if (--f[h[a[x]]]==0) g[pos[h[a[x]]]]--;
    h[a[x]]++;
    if (++f[h[a[x]]]==1) g[pos[h[a[x]]]]++;
}
void del(int x)
{
    if (--f[h[a[x]]]==0) g[pos[h[a[x]]]]--;
    h[a[x]]--;
    if (++f[h[a[x]]]==1) g[pos[h[a[x]]]]++;
}
void add_time(int k)
{
    int x=b[k].x,y=b[k].y,z=b[k].z;
    if (x>=l&&x<=r) del(x);
    b[k].z=a[x];
    a[x]=y;
    if (x>=l&&x<=r) add(x);
}
void del_time(int k)
{
    int x=b[k].x,y=b[k].y,z=b[k].z;
    if (x>=l&&x<=r) del(x);
    a[x]=z;
    if (x>=l&&x<=r) add(x);
}
int query()
{
    int i=1;
    for (int i=1;i<=pos[n];i++)
        if (g[i]!=R[i]-L[i]+1) break;
    for (int j=L[i];j<=R[i];j++)
        if (!f[j]) return j;
}
int main()
{
    n=read(); m=read();
    int blo=pow(n,2.0/3);
    for (int i=1;i<=n;i++)
    {
        pos[i]=(i-1)/blo+1;
        if (!L[pos[i]]) L[pos[i]]=i;
        R[pos[i]]=i;
    }
    for (int i=1;i<=n;i++) a[i]=read(),c[++cnt]=a[i];
    int now=0;
    for (int i=1;i<=m;i++)
    {
        int op=read(),l=read(),r=read();
        if (op==1) q[++qn]=(node){l,r,i,0,now};
        else b[++now]=(nodee){l,r,0},c[++cnt]=b[now].y;
    }
    sort(c+1,c+1+cnt);
    cnt=unique(c+1,c+cnt+1)-c-1;
    //for (int i=1;i<=cnt;i++) printf("%d ",c[i]); puts("");
    for (int i=1;i<=n;i++) a[i]=lower_bound(c+1,c+1+cnt,a[i])-c;
    for (int i=1;i<=now;i++) b[i].y=lower_bound(c+1,c+1+cnt,b[i].y)-c;
    //for (int i=1;i<=n;i++) printf("%d ",a[i]); puts("");
    sort(q+1,q+1+qn,cmp1);
    l=1; r=0; now=0;
    for (int i=1;i<=qn;i++)
    {
        while (r<q[i].r) add(++r);
        while (r>q[i].r) del(r--);
        while (l>q[i].l) add(--l);
        while (l<q[i].l) del(l++);
        while (now<q[i].tim) add_time(++now);
        while (now>q[i].tim) del_time(now--);
        q[i].ans=query();
    }
    sort(q+1,q+1+qn,cmp2);
    for (int i=1;i<=qn;i++) printf("%d\n",q[i].ans);
    return 0;
}
View Code