C小A的数字

要想让所得数字最小,需要让每一位的数字最小,那么假如原数字是0,这一位就填充1,否则填充0,,不过有一个例外,那就是所有数字都是0,这样的话就需要找到最小的一位正数数,使得跟原数字末尾不一样

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int t=sc.nextInt();
        for(int i=0;i<t;i++){
            String n=sc.next(),ans="";
            for(char c:n.toCharArray()){
                ans+=c=='0'?1:0;
            }
            if(Long.parseLong(ans)==0){
                ans=n.charAt(n.length()-1)=='1'?"2":"1";
            }
            System.out.println(Long.parseLong(ans));
        }
    }
}

E小A的任务

离散化b到最多n个数字,利用两个树状数组,完成了b任务的数量,另一个记录累加值,又看到了q最大是100,因此每增加一个A任务,需要对q个询问中的小于等于当前已考虑任务的完成情况计算最小值 总体时间复杂度为O(n*(logn))^2

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),q=sc.nextInt(),a[]=new int[n+5],b[]=new int[n+5],map1[]=new int[n+5],query[]=new int[q];
        TreeSet<Integer> set=new TreeSet<>();
        Map<Integer,Integer> map2=new HashMap<>();
        for(int i=1;i<=n;i++){
            a[i]=sc.nextInt();
        }
        for(int i=1;i<=n;i++){
            b[i]=sc.nextInt();
            set.add(b[i]);
        }
        int p=1;
        for(int c:set){
            map1[p]=c;
            map2.put(c,p);
            p++;
        }
        for(int i=0;i<q;i++){
            query[i]=sc.nextInt();
        }
        long count[]=new long[p+5],sum[]=new long[p+5],ans[]=new long[q],pre=0;
        Arrays.fill(ans,(long)8e18);
        for(int i=1;i<=n;i++){
            pre+=a[i];
            update(count,map2.get(b[i]),1);
            update(sum,map2.get(b[i]),b[i]);
            for(int j=0;j<q;j++){
                if(query[j]<=i){
                    int l=0,r=p;
                    while(l<r){
                        int mid=(l+r)>>1;
                        if(get(count,mid)>=query[j]){
                            r=mid;
                        }
                        else{
                            l=mid+1;
                        }
                        if(l==r-1){
                            if(get(count,l)>=query[j]){
                                r=l;
                            }
                            break;
                        }
                    }
                    ans[j]=Math.min(ans[j],pre+get(sum,r)-(get(count,r)-query[j])*map1[r]);
                }
            }
        }
        for(long s:ans){
            System.out.println(s);
        }
    }
    static void update(long arr[],int idx,int inc){
        for(int i=idx;i<arr.length;i+=i&-i){
            arr[i]+=inc;
        }
    }
    static long get(long arr[],int idx){
        long ans=0;
        for(int i=idx;i!=0;i-=i&-i){
            ans+=arr[i];
        }
        return ans;
    }
}

D小A的线段(easy version)and F小A的线段(hard version)

总体思路参照:链接

import java.util.*;
public class Main{
    static int mod=998244353;
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        TreeSet<Integer> set=new TreeSet<>();
        int n=sc.nextInt(),m=sc.nextInt(),arr[][]=new int[m][];
        set.add(0);
        set.add(1);
        set.add(n);
        for(int i=0;i<m;i++){
            int st=sc.nextInt(),ed=sc.nextInt();
            set.add(st-1);
            set.add(st);
            set.add(ed);
            set.add(ed+1);
            arr[i]=new int[]{st,ed};
        }
        set.remove(n+1);
        Map<Integer,Integer> map=new HashMap<>();
        int p=0,ans[][]=new int[900][900];
        for(int a:set){
            map.put(a,p);
            p++;
        }
        for(int i=0;i<m;i++){
            arr[i][0]=map.get(arr[i][0]);
            arr[i][1]=map.get(arr[i][1]);
        }
        ans[0][0]=1;
        //ans[i][j]代表的是[0,i]覆盖两次,(i,j]覆盖一次的方案数
        Arrays.sort(arr,(a,b)->a[0]==b[0]?a[1]-b[1]:a[0]-b[0]);
        for(int a[]:arr){
            int temp[][]=new int[p+1][];
            for(int i=0;i<=p;i++){
                temp[i]=ans[i].clone();
            }
            //[a[0],a[1]]
            for(int i=0;i<=p;i++){
                for(int j=i;j<=p;j++){
                    if(j==a[0]-1){
                        temp[i][a[1]]=(temp[i][a[1]]+ans[i][j])%mod;
                    }
                    else if(i>=a[0]-1){
                        //效率最高的方法就是老老实实分类讨论,而不是妄想一行解决
                        if(a[1]<=i){
                            temp[i][j]=(temp[i][j]+ans[i][j])%mod;
                        }
                        else if(a[1]<=j){
                            temp[a[1]][j]=(temp[a[1]][j]+ans[i][j])%mod;
                        }
                        else{
                            temp[j][a[1]]=(temp[j][a[1]]+ans[i][j])%mod;
                        }
                    }
                }
            }
            ans=temp;
        }
        System.out.println(ans[p-1][p-1]);
    }
}