C~F题解
对于比特位多于一个的正数,可以分解为该数字去掉最低位以及最低位的异或,而对于比特位单独的数字,则分解为该数字加1和“它自己跟它加1异或后的数”,时间复杂度O(T)
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 a=sc.nextInt();
System.out.println(Integer.bitCount(a)==1?a+1+" "+(a^(a+1)):(a&-a)+" "+(a&(a-1)));
}
}
}
先排序,那么从大到小,尝试让相邻的两个作为较大边,既可以保证两边之和尽可能大,又可以保证边之差尽可能小,从而直接验证较小的那个相邻的数是否可以即可,时间复杂度O(Tnlogn)
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(),a[]=new int[n];
for(int j=0;j<n;j++){
a[j]=sc.nextInt();
}
Arrays.sort(a);
long ans=-1;
for(int j=n-2;j>0;j--){
if(a[j+1]-a[j]<a[j-1]){
ans=(long)a[j+1]+a[j]+a[j-1];
break;
}
}
System.out.println(ans);
}
}
}
用差分来维护快乐时段,需要注意快乐时间段的可能跨天,,哈希集合来维护奶茶,直接按题意模拟,时间复杂度O(n+m+q+C)
,其中C==1440
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),m=sc.nextInt(),count[]=new int[1500];
Set<String> set=new HashSet<>();
for(int i=0;i<n;i++){
int start=find(sc.next()),end=find(sc.next());
count[start]++;
count[end+1]--;
if(start>=end){
count[0]++;
}
}
for(int i=1;i<1440;i++){
count[i]+=count[i-1];
}
for(int i=0;i<m;i++){
set.add(sc.next());
}
int q=sc.nextInt();
for(int i=0;i<q;i++){
boolean invited=true,stayed=true;
int inviteTime=find(sc.next());
if(inviteTime>=120||count[inviteTime]==0){
invited=false;
}
if(find(sc.next())>find(sc.next())){
stayed=false;
}
if(!set.contains(sc.next())){
stayed=false;
}
System.out.println(invited?(stayed?"Winner xqq":"Joker xqq"):"Loser xqq");
}
}
static int find(String s){
return Integer.parseInt(s.substring(0,2))*60+Integer.parseInt(s.substring(3));
}
}
首先对于某个长度的翻转前缀,lcp的具有二段性,因此可以二分,,那么判断字符串相等的时候可以合理利用字符串哈希,需要分别几段s和t的正哈希以及s的反哈希,在判断的时候需要根据前缀个所判断lcp的大小关系稍微分类讨论,时间复杂度O(C+Tnlogn)
,其中C==1e6
import java.util.*;
public class Main{
static long mod=(int)1e9+9,base=307,pow[]=new long[(int)1e6+10];
public static void main(String args[]){
pow[0]=1;
for(int i=1;i<=1e6;i++){
pow[i]=pow[i-1]*base%mod;
}
Scanner sc=new Scanner(System.in);
int T=sc.nextInt();
for(int i=0;i<T;i++){
int n=sc.nextInt();
String s=sc.next(),t=sc.next();
//分别代表的是s的正哈希,t的正哈希,s的反哈希
long hash1[]=new long[n+5],hash2[]=new long[n+5],hash3[]=new long[n+5];
for(int j=1;j<=n;j++){
hash1[j]=(hash1[j-1]*base+s.charAt(j-1))%mod;
hash2[j]=(hash2[j-1]*base+t.charAt(j-1))%mod;
hash3[n-j+1]=(hash3[n-j+2]*base+s.charAt(n-j))%mod;
}
int max=0,idx=1;
for(int j=1;j<=n;j++){
int l=0,r=n;
while(l<r){
int mid=(l+r)>>1;
if(check(j,mid,hash1,hash2,hash3)){
l=mid;
}
else{
r=mid-1;
}
if(l==r-1){
if(check(j,r,hash1,hash2,hash3)){
l=r;
}
break;
}
}
if(l>max){
max=l;
idx=j;
}
}
System.out.println(max+" "+idx);
}
}
static boolean check(int last,int len,long hash1[],long hash2[],long hash3[]){
return hash2[len]==(len<=last?(hash3[last-len+1]+mod-hash3[last+1]*pow[len]%mod)%mod:((hash3[1]+mod-hash3[last+1]*pow[last]%mod)%mod*pow[len-last]%mod+hash1[len]+mod-hash1[last]*pow[len-last]%mod)%mod);
}
}
听说还有线性方法。。。还不会Z函数,等等