D~G Java题解,代码已去除冗余
D 小苯的蓄水池(easy) && E 小苯的蓄水池(hard)
本质上就是一个区间合并,为保证可以查询修改某个不大于端点的值,选用有序映射来表示区间,每个区间端点最多插入或者删除一次,时间复杂度O(nlogn+m)
import java.util.*;
import java.io.*;
public class Main{
public static void main(String args[]) throws IOException{
BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
String arr[]=bf.readLine().split(" ");
int n=Integer.parseInt(arr[0]),m=Integer.parseInt(arr[1]);
arr=bf.readLine().split(" ");
double pre[]=new double[n+1];
TreeMap<Integer,Integer> map=new TreeMap<>();
for(int i=1;i<=n;i++){
pre[i]=pre[i-1]+Integer.parseInt(arr[i-1]);
map.put(i,i);
}
for(int i=0;i<m;i++){
arr=bf.readLine().split(" ");
if(arr[0].equals("1")){
int l=map.floorKey(Integer.parseInt(arr[1])),r=map.get(map.floorKey(Integer.parseInt(arr[2])));
map.put(l,r);
while(map.higherKey(l)!=null){
int p=map.higherKey(l);
if(p>r){
break;
}
map.remove(p);
}
}
else{
int idx1=map.floorKey(Integer.parseInt(arr[1])),idx2=map.get(idx1);
bw.write((pre[idx2]-pre[idx1-1])/(idx2-idx1+1)+"\n");
}
}
bw.flush();
}
}
参考资料--->首先确定答案的首字母是哪一个,这个很简单,,,,接着就是判断同种字母被提前后的字典序,对于不在连续组内的两个字母提前方式,位置较前的字母,需要判断它后边的第一个不同字母的相对字典序,时间复杂度'O(Tn)'
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++){
int n=sc.nextInt(),k=sc.nextInt(),next[]=new int[n],start=0;
List<Integer> idx[]=new List[26];
for(int j=0;j<26;j++){
idx[j]=new ArrayList<>();
}
Arrays.fill(next,-1);
String s=sc.next();
for(int j=n-1;j>=0;j--){
if(j<n-1){
next[j]=s.charAt(j)==s.charAt(j+1)?next[j+1]:j+1;
}
idx[s.charAt(j)-'a'].add(j);
}
for(;idx[start].size()<k;k-=idx[start].size(),start++){
}
Deque<Integer> deque=new ArrayDeque<>();
for(int a:idx[start]){
if(next[a]==-1||s.charAt(a)<s.charAt(next[a])){
deque.addLast(a);
}
else{
deque.addFirst(a);
}
}
for(int j=0;j<k-1;j++){
deque.removeFirst();
}
int ans=deque.removeFirst();
System.out.println(s.charAt(ans)+s.substring(0,ans)+s.substring(ans+1));
}
}
}
数位动态规划,需要预处理10位以下的,以每种数字开头且数字出现情况mask的数组数量,再按位计算,时间复杂度O(10^3*2^10+Tlog(n)*100*2^10)
import java.util.*;
public class Main{
static int count[][][]=new int[10][10][1024],mex[]=new int[1024],pre[][]=new int[10][12];
static{
for(int j=1;j<1024;j++){
for(int i=0;;i++){
if(((j+1)>>i&1)==1){
mex[j]=i;
break;
}
}
}
count[0][0][0]=1;
for(int i=1;i<10;i++){
for(int j=0;j<10;j++){
for(int k=0;k<1024;k++){
for(int p=0;p<10;p++){
count[i][j][k|(1<<j)]+=count[i-1][p][k];
}
}
}
}
for(int i=1;i<10;i++){
pre[i]=pre[i-1].clone();
for(int j=0;j<1024;j++){
for(int k=1;k<10;k++){
pre[i][mex[j]]+=count[i][k][j];
}
}
}
}
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
for(int i=0;i<t;i++){
int x=sc.nextInt(),k=sc.nextInt(),ans1[]=find(x+k),ans2[]=find(x-1);
for(int j=10;;j--){
if(ans1[j]!=ans2[j]){
System.out.println(j+" "+(ans1[j]-ans2[j]));
break;
}
}
}
}
static int[] find(int k){
if(k==0){
return new int[12];
}
List<Integer> list=new ArrayList<>();
while(k!=0){
list.add(k%10);
k/=10;
}
int size=list.size(),ans[]=pre[size-1].clone(),mask=0;
for(int i=size-1;i>=0;i--){
int a=list.get(i);
for(int j=(i==size-1?1:0);j<a;j++){
int curMask=mask|(1<<j);
//还剩下i位
for(int p=0;p<10;p++){
for(int w=0;w<1024;w++){
ans[mex[curMask|w]]+=count[i][p][w];
}
}
}
mask|=1<<a;
if(i==0){
ans[mex[mask]]++;
}
}
return ans;
}
}