要想让所得数字最小,需要让每一位的数字最小,那么假如原数字是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));
}
}
}
离散化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]);
}
}