26spring做题记录 - March
2026.3做题记录及3月数算月考
2026.3.1
相交链表
from typing import Optional:返回目标类型或None
一个链表为a+c,另一个链表为b+c。走完一个开始走另一个,最终两个指针都走a+b+c,并在相交点相遇。
from typing import Optional
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
if not headA or not headB:
return None
pA, pB = headA, headB
while pA != pB:
pA = pA.next if pA else headB
pB = pB.next if pB else headA
return pA
def create_linked_list(arr):
if not arr:
return None
head = ListNode(arr[0])
cur = head
for val in arr[1:]:
cur.next = ListNode(val)
cur = cur.next
return head
a=[4,1,8,4,5]
b=[5,6,1,8,4,5]
# 注意:这里直接生成的b包含后续节点,但为了模拟相交,我们会把b的尾部截断并接上a的相交部分
headA = create_linked_list(a)
headB = create_linked_list(b[:3]) # 只生成 [5,6,1]
# 模拟相交:相交点是 8
# a中8的位置是索引2 (4->1->8)
intersect_node = headA.next.next
# 将b的尾部接上相交节点
curB = headB
while curB.next:
curB = curB.next
curB.next = intersect_node
print(f"Intersect val: {Solution().getIntersectionNode(headA, headB).val}")
反转链表
每次存三个节点。
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur=head
if(cur==None):
return None
qaq=cur.next
head.next=None
while(qaq!=None):
tmp=qaq.next
qaq.next=cur
cur=qaq
qaq=tmp
return cur
def init(arr):
head=ListNode(arr[0])
cur=head
for i in range(1,len(arr)):
cur.next=ListNode(arr[i])
cur=cur.next
return head
arr=[1,2,3,4,5]
print(Solution().reverseList(init(arr)).val)
链表的中间结点
两倍速度指针/先扫一遍记录长度
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur=head
n=1
while(cur.next!=None):
n+=1
cur=cur.next
n=n//2
cur=head
while(n):
cur=cur.next
n-=1
return cur
回文链表
先找中点然后反转后半部分。然后双指针同时跑一遍。
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reverseList(head):
cur=head
if(cur==None):
return None
qaq=cur.next
head.next=None
while(qaq!=None):
tmp=qaq.next
qaq.next=cur
cur=qaq
qaq=tmp
return cur
def isPalindrome(self, head: Optional[ListNode]) -> bool:
fast=head
slow=head
while(fast.next!=None and fast.next.next!=None):
slow=slow.next
fast=fast.next.next
head2=Solution.reverseList(slow)
head1=head
if(head1.val!=head2.val):
return False
while(head1.next!=None and head2.next!=None):
head1=head1.next
head2=head2.next
if(head1.val!=head2.val):
return False
return True
def init(arr):
head=ListNode(arr[0])
cur=head
for i in range(1,len(arr)):
cur.next=ListNode(arr[i])
cur=cur.next
return head
arr=[1,2,3,2,1]
print(Solution().isPalindrome(init(arr)))
环形链表
哈希表。
from typing import Optional
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if(head==None):
return False
a=set()
cur=head
a.add(cur)
while(cur.next!=None):
cur=cur.next
if(cur in a):
return True
a.add(cur)
return False
环形链表 II
快慢指针。
from typing import Optional
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow=head
fast=head
if(fast==None):
return None
if(fast.next==None):
return None
while(True):
slow=slow.next
fast=fast.next.next
if(fast==None or fast.next==None):
return None
if(fast==slow):
break
cur=head
while(slow!=cur):
slow=slow.next
cur=cur.next
return cur
合并两个有序链表
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
cur1=list1
cur2=list2
if(cur1==None and cur2==None):
return None
head=ListNode()
cur3=head
while(cur1!=None and cur2!=None):
if(cur1.val>cur2.val):
cur3.next=cur2
cur2=cur2.next
cur3=cur3.next
else:
cur3.next=cur1
cur1=cur1.next
cur3=cur3.next
if(cur1!=None):
cur3.next=cur1
if(cur2!=None):
cur3.next=cur2
return head.next
删除链表的倒数第 N 个结点
设一个快n-1个结点的指针
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
slow=head
fast=head
for i in range(n-1):
fast=fast.next
# if(fast==None):
# return None
if(fast.next==None):
tmp=slow.next
slow.next=None
return tmp
while(fast.next.next!=None):
slow=slow.next
fast=fast.next
qaq=slow.next.next
slow.next=qaq
return head
2026.3.2
两两交换链表中的节点
设置一个dummy哑节点作为最头上的节点,这样头两个节点就不需要特殊处理。a-b-c变为a-c-b,然后当前节点由a移到b即可。
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
if(head==None):
return None
if(head.next==None):
return head
dummy=ListNode(0)
dummy.next=head
cur=dummy
while(cur.next!=None and cur.next.next!=None):
cur1=cur.next
cur2=cur.next.next
cur1.next=cur2.next
cur2.next=cur1
cur.next=cur2
cur=cur1
return dummy.next
Fraction类
1.python自带Fraction类:
from fractions import Fraction
a,b,c,d=map(int,input().split())
x=Fraction(a,b)
y=Fraction(c,d)
print(x+y)
f = Fraction(6, 8)
print(f.numerator, f.denominator) #3 4
2.f-string f”{a}output{b:.2f}” #保留两位小数 3.必须参数:调用时必须提供的参数 默认参数:定义函数时已提供默认值,必须在必须函数后面
def greet(name, age=18, city="北京"): # age 和 city 有默认值
print(f"{name} 今年 {age} 岁,住在{city}")
greet("小明") # 小明 今年 18 岁,住在北京
greet("小红", 20) # 小红 今年 20 岁,住在北京
greet("小刚", 22, "上海") # 小刚 今年 22 岁,住在上海
greet("小李", city="广州") # 小李 今年 18 岁,住在广州(指定city参数)
可变参数:
*args:任意数量,打包成元组
**kwargs:打包成字典
4.__add__(),__str__()为特殊方法名,设置后可直接用+,print()调用。
def gcd(a,b):
a=abs(a)
b=abs(b)
if(a<b):
a,b=b,a
while(a%b!=0):
c=a%b
a=b
b=c
return b
class Fraction:
def __init__(self,numerator,denominator):
self.numerator=numerator
self.denominator=denominator
self.simplify()
def simplify(self):
a=self.numerator
b=self.denominator
if(a==0):
self.numerator=0
self.denominator=1
return
c=gcd(a,b)
self.numerator=a//c
self.denominator=b//c
def __add__(self,other):
a,b,c,d=self.numerator,self.denominator,other.numerator,other.denominator
e=a*d+b*c
f=b*d
return Fraction(e,f)
def __str__(self):
a=self.numerator
b=self.denominator
if(b==1):
return f"{a}"
return f"{a}/{b}"
a,b,c,d=map(int,input().split())
x=Fraction(a,b)
y=Fraction(c,d)
print(x+y)
模型整理
1.f-string中的字符串都用单引号括,不然多个双引号会编译报错 2.对精度有要求则可str转decimal.Decimal类型
from collections import defaultdict
from decimal import Decimal
n=int(input())
models=defaultdict(list)
for i in range(n):
a,b=input().split('-')
if(b[-1]=='M'):
c=Decimal(b[0:-1])*1000000
elif(b[-1]=='B'):
c=Decimal(b[0:-1])*1000000000
models[a].append(c)
ans=dict(sorted(models.items(),key=lambda x:x[0]))
for k in ans:
ans[k].sort()
tmp=[]
for i in ans[k]:
if(i>=1000000 and i<1000000000):
s=str(i/1000000)
tmp.append(s+"M")
else:
s=str(i/1000000000)
tmp.append(s+"B")
print(f"{k}: {', '.join(tmp)}")
颠倒二进制位
每一次把最后一位放到对应位置(通过将最后一位左移并或运算实现),然后右移一位。
class Solution:
def reverseBits(self, n: int) -> int:
ans=0
for i in range(32):
if(n==0):
break
ans|=((n&1)<<(31-i))
n=n>>1
return ans
print(Solution().reverseBits(43261596))
O(1)方法:位运算分治。 颠倒的方法是分成两半,颠倒后交换。两半可以继续这么下去。 颠倒的方法是通过与运算取不同的位然后移动。
m0 = 0x55555555 # 01010101 ...
m1 = 0x33333333 # 00110011 ...
m2 = 0x0f0f0f0f # 00001111 ...
m3 = 0x00ff00ff # 00000000111111110000000011111111
m4 = 0x0000ffff # 00000000000000001111111111111111
class Solution:
def reverseBits(self, n: int) -> int:
n=(n>>1&m0)|((n&m0)<<1)
n=(n>>2&m1)|((n&m1)<<2)
n=(n>>4&m2)|((n&m2)<<4)
n=(n>>8&m3)|((n&m3)<<8)
n=(n>>16&m4)|((n&m4)<<16)
return n
2026.3.3
K 个一组翻转链表
每次tail从开头向后移k位。单独翻转后把前后接上。
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reverse(self,head,tail):
cur1=head
cur2=cur1.next
while(cur1!=tail):
cur3=cur2.next
cur2.next=cur1
cur1=cur2
cur2=cur3
return tail,head
def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
dummy=ListNode(0)
dummy.next=head
pre=dummy
while(head):
head=pre.next
tail=pre
for i in range(k):
tail=tail.next
if(tail==None):
return dummy.next
tmp=tail.next
head,tail=Solution().reverse(head,tail)
pre.next=head
tail.next=tmp
pre=tail
return dummy.next
def make(self,arr):
if not arr:
return None
head = ListNode(arr[0])
cur = head
for val in arr[1:]:
cur.next = ListNode(val)
cur = cur.next
return head
arr=[1,2,3,4,5]
head=Solution().make(arr)
k=3
head=Solution().reverseKGroup(head,k)
while(head):
print(head.val)
head=head.next
奇偶链表
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if(head==None or head.next==None):
return head
oddhead=head
evenhead=head.next
odd=oddhead
even=evenhead
while(even and even.next):
t1=even.next
even.next=t1.next
odd.next=t1
odd=odd.next
even=even.next
odd.next=evenhead
return head
随机链表的复制
交叉链表。新点的random就是原点的random的下一个节点。 亦可哈希表。
from typing import Optional
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
cur=head
if(head==None):
return None
while(cur):
t=Node(cur.val)
t.next=cur.next
cur.next=t
cur=t.next
cur=head
while(cur):
if(cur.random):
cur.next.random=cur.random.next
cur=cur.next.next
newhead=head.next
cur=head
newcur=Node(0,head)
while(cur):
copy=cur.next
newcur.next=copy
cur.next=copy.next
cur=cur.next
newcur=newcur.next
return newhead
排布二进制网格的最少交换次数
由于越往下需要满足的条件越宽松,因此对每行向下遍历,遇到符合条件的就交换上去。
class Solution:
def minSwaps(self, grid: list[list[int]]) -> int:
n=len(grid)
zeroes=[n]*n
for i in range(n):
for j in range(n-1,-1,-1):
if(grid[i][j]==1):
zeroes[i]=n-1-j
break
ans=0
for i in range(n):
qaq=n-1-i
flag=0
for j in range(i,n):
if(zeroes[j]>=qaq):
flag=1
ans+=(j-i)
zeroes[i+1:j+1]=zeroes[i:j]
break
if(flag==0):
return -1
return ans
print(Solution().minSwaps([[0,0,1],[1,1,0],[1,0,0]]))
最大点数(同2048规则)
直接搜索即可。 模拟的时候注意不要更改原数组,数据量较低使用deepcopy即可。先把所有数字移到一边(移动零),再合并,再移动零。
from copy import deepcopy
m,n,p=map(int,input().split())
def left(b):
a=deepcopy(b)
global m,n
for i in range(m):
cur=0
for j in range(n):
if(a[i][j]!=0):
a[i][cur],a[i][j]=a[i][j],a[i][cur]
cur+=1
for j in range(n):
if(a[i][j]!=0 and j!=n-1 and a[i][j]==a[i][j+1]):
a[i][j]*=2
a[i][j+1]=0
cur=0
for j in range(n):
if(a[i][j]!=0):
a[i][cur],a[i][j]=a[i][j],a[i][cur]
cur+=1
return a
def right(b):
a=deepcopy(b)
global m,n
for i in range(m):
cur=n-1
for j in range(n-1,-1,-1):
if(a[i][j]!=0):
a[i][cur],a[i][j]=a[i][j],a[i][cur]
cur-=1
for j in range(n-1,-1,-1):
if(a[i][j]!=0 and j!=0 and a[i][j]==a[i][j-1]):
a[i][j]*=2
a[i][j-1]=0
cur=n-1
for j in range(n-1,-1,-1):
if(a[i][j]!=0):
a[i][cur],a[i][j]=a[i][j],a[i][cur]
cur-=1
return a
def up(b):
a=deepcopy(b)
global m,n
for j in range(n):
cur=0
for i in range(m):
if(a[i][j]!=0):
a[cur][j],a[i][j]=a[i][j],a[cur][j]
cur+=1
for i in range(m):
if(a[i][j]!=0 and i!=m-1 and a[i][j]==a[i+1][j]):
a[i][j]*=2
a[i+1][j]=0
cur=0
for i in range(m):
if(a[i][j]!=0):
a[cur][j],a[i][j]=a[i][j],a[cur][j]
cur+=1
return a
def down(b):
a=deepcopy(b)
global m,n
for j in range(n):
cur=m-1
for i in range(m-1,-1,-1):
if(a[i][j]!=0):
a[cur][j],a[i][j]=a[i][j],a[cur][j]
cur-=1
for i in range(m-1,-1,-1):
if(a[i][j]!=0 and i!=0 and a[i][j]==a[i-1][j]):
a[i][j]*=2
a[i-1][j]=0
cur=m-1
for i in range(m-1,-1,-1):
if(a[i][j]!=0):
a[cur][j],a[i][j]=a[i][j],a[cur][j]
cur-=1
return a
def dfs(a,step):
global ans,m,n,p
# print("TEST",step)
# for i in range(m):
# for j in range(n):
# print(a[i][j],end=' ')
# print()
if(step==p):
res=0
for i in range(m):
for j in range(n):
res=max(res,a[i][j])
ans=max(ans,res)
return
dfs(left(a),step+1)
dfs(right(a),step+1)
dfs(up(a),step+1)
dfs(down(a),step+1)
return
a=[]
ans=0
for i in range(m):
t=list(map(int,input().split()))
a.append(t)
dfs(a,0)
print(ans)
2026.3.5
max-cut近似
随机选点,α=2.
直接存边。
srand(time(0));
rand()%2->以0.5概率决定。
#include<bits/stdc++.h>
using namespace std;
struct Edge{
int u,v;
};
int main(){
srand(time(0));
int qaq;
cin>>qaq;
while(qaq--){
int n,m;
cin>>n>>m;
vector<Edge> edges(m);
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
edges[i].u=u;
edges[i].v=v;
}
int ans=0;
vector<bool> s(n+1);
vector<bool> s0(n+1);
for(int t=0;t<100;t++){
int res=0;
for(int i=1;i<=n;i++){
if(rand()%2==0) s[i]=1;
else s[i]=0;
}
for(int i=0;i<m;i++){
if(s[edges[i].u]^s[edges[i].v]==1) res++;
}
if(res>ans){
s0=s;
ans=res;
}
}
set<int> st;
for(int i=1;i<=n;i++){
if(s0[i]==1){
st.insert(i);
}
}
cout<<st.size()<<endl;
for(int x : st){
cout<<x<<" ";
}
cout<<endl;
}
return 0;
}
连接连续二进制数字
连接=左移若干位然后或运算。
.bit_length()返回二进制的位数
class Solution:
def concatenatedBinary(self, n: int) -> int:
ans=0
mod=1000000007
for i in range(1,n+1):
t=i.bit_length()
ans=(ans<<t)|i
ans%=mod
return ans
print(Solution().concatenatedBinary(3))
二进制间距
class Solution:
def binaryGap(self, n: int) -> int:
ans=0
cnt=1
flag=0
while(n):
if(flag==1 and n&1==0):
cnt+=1
elif(n&1==1):
if(flag==0):
flag=1
else:
ans=max(ans,cnt)
cnt=1
n>>=1
return ans
print(Solution().binaryGap(5))
将二进制表示减到 1 的步骤数
四行代码,直观了解背后原理 连续的1进位最后会多一次操作,而连续的1的个数相当于头尾的1之间0的个数。答案即为n+1+cnt。
class Solution:
def numSteps(self, s: str) -> int:
n=len(s)
idx=s[::-1].find('1')
if(idx==n-1):
return n-1
idx=n-1-idx
ans=n+1
for i in range(0,idx):
if(s[i]=='0'):
ans+=1
return ans
print(Solution().numSteps("1101"))
统计单比特整数
bit_count():1的个数 bit_length():二进制长度
class Solution:
def countMonobit(self, n: int) -> int:
t=n.bit_length()
ans=t
if(n.bit_count()==n.bit_length()):
ans+=1
return ans
print(Solution().countMonobit(4))
检查一个字符串是否包含所有长度为 K 的二进制子串
思路是把字符串中每个长度为k的字串加入集合中。可以使用滑动窗口,集合中存十进制数,这样可以根据上一个数更新下一个。
class Solution:
def hasAllCodes(self, s: str, k: int) -> bool:
n=len(s)
st=set()
if(k>n):
return False
num=int(s[:k],2)
st.add(num)
for i in range(k,n):
num=(num-(int(s[i-k])<<(k-1)))*2+int(s[i])
st.add(num)
return len(st)==(1<<k)
print(Solution().hasAllCodes("00110110", 2))
多项式加法
defaultdict(int) d.items() 两个多项式不一定一样长。
from collections import defaultdict
qaq=int(input())
for _ in range(qaq):
a=list(map(int,input().split()))
b=list(map(int,input().split()))
n=len(a)
n//=2
m=len(b)
m//=2
d=defaultdict(int)
for i in range(n):
if(a[2*i+1]<0):
break
d[a[2*i+1]]+=a[2*i]
for i in range(m):
if(b[2*i+1]<0):
break
d[b[2*i+1]]+=b[2*i]
ans=dict(sorted(d.items(),key=lambda x:-x[0]))
res=[]
for k,v in ans.items():
if(v==0):
continue
res.append(f"[ {v} {k} ]")
print(" ".join(res))
Number Sequence
1.取数位个数:len(str(i)),取对数可能有精度问题。 2.bisect_left:大于等于,bisect:大于 3.取数中的某一位:转成字符串。
from math import log
from bisect import bisect_left
t=int(input())
digit=[0]*35000
sum=[0]*35000
sum[1]=1
pre=[0,1]
for i in range(1,35000):
digit[i]=len(str(i))
for i in range(2,35000):
sum[i]=sum[i-1]+digit[i]
pre.append(pre[i-1]+sum[i])
for _ in range(t):
n=int(input())
ans=bisect_left(pre,n)
tmp=n-pre[ans-1]
for i in range(1,ans+1):
tmp-=digit[i]
if(tmp<=0):
tmp+=digit[i]
print(str(i)[tmp-1])
break
2026.3.7
Fingerprinting
随机生成[0,1]的列向量,与两边相乘,复杂度减为O(n^2).比对生成的矩阵的指纹是否相同。
#include<bits/stdc++.h>
using namespace std;
int randint(const unsigned int &seed) {
static unsigned int x = seed;
x = (x * 23333LL + 23327) % 1000000007;
return x % 20 - 10;
}
int a[3005][3005],b[3005][3005],c[3005][3005];
long long a0[3005],b0[3005],c0[3005];
int main(){
int n,seed;
scanf("%d",&n);
scanf("%d",&seed);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n;j++) {
a[i][j] = randint(seed);
b[i][j] = randint(seed);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&c[i][j]);
}
}
int d[n+1];
minstd_rand gen;
bool flag=1;
for(int k=1;k<=2;k++){
for(int i=1;i<=n;i++){
d[i]=gen()&1;
}
memset(a0,0,sizeof(a0));
memset(b0,0,sizeof(b0));
memset(c0,0,sizeof(c0));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
b0[i]+=b[i][j]*d[j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
c0[i]+=c[i][j]*d[j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
a0[i]+=a[i][j]*b0[j];
}
}
for(int i=1;i<=n;i++){
if(a0[i]!=c0[i]){
flag=0;
break;
}
}
}
if(flag) printf("YES\n");
else printf("NO \n");
return 0;
}
排队
t=int(input())
def find(x):
if(x==fa[x]):
return x
fa[x]=find(fa[x])
return fa[x]
def merge(x,y):
if(find(x)!=find(y)):
fa[find(x)]=find(y)
for _ in range(t):
n,m=map(int,input().split())
fa=[_ for _ in range(n+1)]
for i in range(m):
x,y=map(int,input().split())
merge(x,y)
ans=[]
for i in range(1,n+1):
ans.append(find(i))
print(" ".join(map(str,ans)))
2026.3.9
区域和检索 - 数组不可变
class NumArray:
def __init__(self, nums: list[int]):
n=len(nums)
sum=[0]*(n+1)
for i in range(n):
sum[i+1]=sum[i]+nums[i]
self.sum=sum
def sumRange(self, left: int, right: int) -> int:
return self.sum[right+1]-self.sum[left]
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)
obj=NumArray([-2, 0, 3, -5, 2, -1])
print(obj.sumRange(0, 2))
print(obj.sumRange(2, 5))
print(obj.sumRange(0, 5))
找出第 N 个二进制字符串中的第 K 位
递归,分析是在前半还是后半,然后推到n-1.
class Solution:
def findKthBit(self, n: int, k: int) -> str:
if(n==1):
return '0'
if(k==(1<<(n-1))):
return '1'
if(k<(1<<(n-1))):
return self.findKthBit(n-1,k)
res=self.findKthBit(n-1,(1<<n)-k)
if(res=='1'):
return '0'
else:
return '1'
print(Solution().findKthBit(3, 1))
2026.3.10
数算课 1.真值表
二维区域和检索 - 矩阵不可变
class NumMatrix:
def __init__(self, matrix: list[list[int]]):
m=len(matrix)
n=len(matrix[0])
sum=[[0 for _ in range(n+1)]for _ in range(m+1)]
for i in range(m):
for j in range(n):
sum[i+1][j+1]=sum[i+1][j]+sum[i][j+1]+matrix[i][j]-sum[i][j]
self.sum=sum
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
return self.sum[row2+1][col2+1]-self.sum[row2+1][col1]-self.sum[row1][col2+1]+self.sum[row1][col1]
# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)
obj=NumMatrix([[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]])
print(obj.sumRegion(2, 1, 4, 3))
print(obj.sumRegion(1, 1, 2, 2))
print(obj.sumRegion(1, 2, 2, 4))
区域和检索 - 数组可修改
树状数组。 【模板】树状数组 1 单点修改,区间查询。 如果区间修改,单点查询,则使用差分数组。 【模板】树状数组 2
class NumArray:
def __init__(self, nums: list[int]):
n=len(nums)
self.num=nums
self.tree=[0]*(n+1)
for i in range(n):
self.add(i+1,nums[i])
def lowbit(x):
return x&(-x)
def add(self,idx,val):
while(idx<len(self.tree)):
self.tree[idx]+=val
idx+=NumArray.lowbit(idx)
def prefix(self,index):
ans=0
while(index>0):
ans+=self.tree[index]
index-=NumArray.lowbit(index)
return ans
def update(self, index: int, val: int) -> None:
self.add(index+1,val-self.num[index])
self.num[index]=val
def sumRange(self, left: int, right: int) -> int:
return self.prefix(right+1)-self.prefix(left)
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(index,val)
# param_2 = obj.sumRange(left,right)
obj=NumArray([1,3,5])
print(obj.sumRange(0,2))
obj.update(1,2)
print(obj.sumRange(0,2))
回文子串
中心扩散法。长度为n的字符串产生2n-1个回文中心[l,r]。
class Solution:
def countSubstrings(self, s: str) -> int:
n=len(s)
ans=0
for i in range(2*n-1):
l=i//2
r=(i+1)//2
while(l>=0 and r<n and s[l]==s[r]):
l-=1
r+=1
ans+=1
return ans
print(Solution().countSubstrings("abc"))
XXXXX
双指针。需要两头加起来不是x的倍数(否则整体不是x的倍数),因此必有一头符合。只删一头即可。
def doit(n,x,a):
s=sum(a)
if(s%x!=0):
return n
else:
i=0
j=n-1
si=sj=0
while(i<n and j>=0):
si+=a[i]
sj+=a[j]
if(si%x!=0 or sj%x!=0):
return j
i+=1
j-=1
return -1
t=int(input())
for _ in range(t):
n,x=map(int,input().split())
a=list(map(int,input().split()))
print(doit(n,x,a))
2026.3.11 月考及练习
生成概率为p的两点分布
每次乘二后减一,以防p=1及整数溢出。
#include <iostream>
#include <cassert>
#include <random>
using namespace std;
const int T = 1e6;
const double eps = 1e-2;
random_device rd;
class Generator{
private:
minstd_rand gen;
public:
int rand(){ return gen() % 2; }
};
int bern(double p, Generator *G){
// 在此处补充你的代码
while(true){
p*=2.0;
int ans=p>=1.0?1:0;
int qaq=G->rand();
p-=ans;
if(qaq==ans){
return ans;
}
}
}
int main(){
double p; int T;
while (cin >> p >> T){
Generator RAND, CHECK;
int tmp = bern(p, &CHECK);
for (int i = 1; i <= T; ++ i){
Generator CHECK;
if (tmp != bern(p, &CHECK)){
// cout << "using external randomness!" << endl;
cout << "WA" << endl;
return 0;
}
}
int c = 0;
for (int i = 1; i <= T; ++ i)
c += bern(p, &RAND);
// cout << "the frequncy is : " << (double)c / T << endl;
if (c < (p - eps) * T || c > (p + eps) * T){
cout << "WA" << endl;
return 0;
}
}
cout << "AC" << endl;
return 0;
}
十进制整数的反码
class Solution:
def bitwiseComplement(self, n: int) -> int:
t=n.bit_length()
return n^((1<<t)-1) if n>0 else 1
print(Solution().bitwiseComplement(5))
从上学期就开始说的打比赛不要急是什么意思! 就是T2被卡了,以及T6交的前两发输出格式都不对。
泰波拿契數
n=int(input())
a=[0,1,1]
for i in range(3,n+1):
a.append(a[i-1]+a[i-2]+a[i-3])
print(a[n])
稳定的符文序列
滑动窗口。每次只有右指针新添加的会影响,右移一位左移若干位。
s=input()
n=len(s)
a=[0]*26
t=set()
left=0
ans=0
cur=0
for i in range(n):
a[ord(s[i])-ord('a')]+=1
cur+=1
while(a[ord(s[i])-ord('a')]>1):
a[ord(s[left])-ord('a')]-=1
cur-=1
left+=1
ans=max(ans,cur)
print(ans)
十进制整数的反码
n=int(input())
t=bin(n)[2:]
ans=""
for i in range(len(t)):
if(t[i]=='0'):
ans+='1'
else:
ans+='0'
print(int(ans,2))
亦可创建全1掩码然后按位异或。
Ultra-QuickSort
求逆序对。
ans=0
def merge(l,r):
global ans
if(l==r):
return
mid=(l+r)>>1
merge(l,mid)
merge(mid+1,r)
i=l
j=mid+1
cur=l
while(i<=mid and j<=r):
if(a[i]>a[j]):
ans+=(mid-i+1)
a_new[cur]=a[j]
cur+=1
j+=1
else:
a_new[cur]=a[i]
cur+=1
i+=1
while(i<=mid):
a_new[cur]=a[i]
cur+=1
i+=1
while(j<=r):
a_new[cur]=a[j]
cur+=1
j+=1
a[l:r+1]=a_new[l:r+1]
while(True):
n=int(input())
if(n==0):
break
a=[]
ans=0
a_new=[0]*n
for i in range(n):
t=int(input())
a.append(t)
merge(0,n-1)
print(ans)
逃离紫罗兰监狱
from collections import deque
r,c,k=map(int,input().split())
a=[]
for i in range(r):
t=input()
a.append(t)
for i in range(r):
for j in range(c):
if(a[i][j]=='S'):
x0=i
y0=j
elif(a[i][j]=='E'):
x1=i
y1=j
q=deque()
vis=[[[0 for _ in range(k+1)]for _ in range(c)]for _ in range(r)]
q.append([x0,y0,0,0])
vis[x0][y0][0]=1
dx=[0,1,0,-1]
dy=[1,0,-1,0]
flag=0
while(q):
x,y,cur,l=q.popleft()
if(flag==1):
break
for i in range(4):
xx=x+dx[i]
yy=y+dy[i]
if(xx>=0 and xx<r and yy>=0 and yy<r):
if(a[xx][yy]=='.'):
if(vis[xx][yy][cur]==0):
vis[xx][yy][cur]=1
q.append([xx,yy,cur,l+1])
elif(a[xx][yy]=='#'):
if(cur<k and vis[xx][yy][cur+1]==0):
vis[xx][yy][cur+1]=1
q.append([xx,yy,cur+1,l+1])
elif(a[xx][yy]=='E'):
flag=1
print(l+1)
break
if(flag==0):
print(-1)
狭路相逢
注意审题,幸存者包括人和怪。因此使用栈,幸存的怪一定在栈底。
from collections import deque
n=int(input())
a=list(map(int,input().split()))
s=deque()
for i in range(n):
if(a[i]>0):
s.append(a[i])
else:
tmp=-a[i]
while(s):
t=s[-1]
if(t<0):
break
s.pop()
if(t>tmp):
t-=tmp
s.append(t)
tmp=0
break
else:
tmp-=t
if(tmp>0):
s.append(-tmp)
print(len(s))
print(" ".join(map(str,s)))
2026.3.12
估计p分位数
#include <bits/stdc++.h>
#include "rank.h"
using namespace std;
int rnk(int n, double p){
minstd_rand gen;
int res[n+1];
int m=4000;
for(int i=0;i<m;i++){
int t=int(double(gen())/gen.max()*n)+1;
res[i]=query(t);
}
sort(res,res+m);
int idx=int(p*m);
if(idx<0) idx=0;
if(idx>=m) idx=m-1;
return res[idx];
}
数字华容道(Easy Version)
左右移动不改变序列奇偶性,上下移动相当于移动(n-1)位,如果n为偶数影响奇偶性,n为奇数则不影响。 因此转化为求整条序列的逆序对。这里采用树状数组。 先把所有数离散化为1-n(这道题不需要),然后从后往前遍历。对当前元素x,答案加上tree[x-1](即在此之前遇到过的小于x的数),然后在tree的x对应位置+1,表示已经遇到过了。
def lowbit(x):
return x&(-x)
class BIT:
def __init__(self,n):
self.n=n
self.tree=[0]*(n+1)
def update(self,idx,x):
while(idx<=self.n):
self.tree[idx]+=x
idx+=lowbit(idx)
def query(self,idx):
ans=0
while(idx>0):
ans+=self.tree[idx]
idx-=lowbit(idx)
return ans
n=int(input())
a=[]
for i in range(n):
t=list(map(int,input().split()))
if(0 in t):
tmp=i
t.remove(0)
a.extend(t)
m=n*n-1
b=BIT(m)
ans=0
for i in range(m-1,-1,-1):
ans+=b.query(a[i]-1)
b.update(a[i],1)
if(n%2==0):
ans+=(n-tmp-1)
if(ans%2==0):
print("yes")
else:
print("no")
else:
if(ans%2==0):
print("yes")
else:
print("no")
数字华容道(Hard Version)
求全排列序列的奇偶性,即求把它还原成1-n正序的交换次数。全排列可以唯一分解为多个循环。一个有 n 个数的循环可以通过 n-1 次元素交换变回递增的序列。
T=int(input())
def cycle(a):
m=len(a)
vis=bytearray(m)
ans=0
for i in range(m):
if(not vis[i]):
res=0
j=i
while(not vis[j]):
vis[j]=1
j=a[j]-1
res+=1
ans=(ans+res-1)&1
return ans
for _ in range(T):
n=int(input())
a=[]
tmp=1
for i in range(n):
t=list(map(int,input().split()))
if(0 in t):
t.remove(0)
if(n%2==0):
tmp=i
a.extend(t)
if((cycle(a)+tmp)&1):
print("yes")
else:
print("no")
2026.3.15
Idiot First Search
拖了三天的题目。 树上dp.dp数组记录每个点向下一趟之后回到原来的点的代价。dp[root]=(dp[l]+1)+(dp[r]+1)+1=dp[l]+dp[r]+3.这里使用后序遍历可以完成更新。 然后使用前序遍历记录每个点的答案。res[i]=dp[i]+res[parent]. 由于递归爆栈需要使用stack手动模拟。后序遍历使用双栈。stack按根左右压入,每次把根压入新栈,这样新栈是根右左的顺序。然后倒着遍历栈,就是左右根的顺序。
import sys
mod=1000000007
# sys.setrecursionlimit(10**7)
# def postorder(root):
# if(left[root]==0 and right[root]==0):
# dp[root]=1
# return 1
# l,r=left[root],right[root]
# postorder(l)
# postorder(r)
# dp[root]=(dp[l]+dp[r]+3)%mod
# def preorder(root,parent_res):
# res[root]=(dp[root]+parent_res)%mod
# l,r=left[root],right[root]
# if(l==0 and r==0):
# return
# preorder(l,res[root])
# preorder(r,res[root])
T=int(input())
for _ in range(T):
n=int(input())
left=[0]*(n+1)
right=[0]*(n+1)
dp=[0]*(n+1)
res=[0]*(n+1)
for i in range(1,n+1):
l,r=map(int,input().split())
left[i]=l
right[i]=r
#postorder(1)
stack=[1]
vis_order=[]
while(stack):
u=stack.pop()
if(u==0):
continue
vis_order.append(u)
stack.append(left[u])
stack.append(right[u])#根右左
for u in reversed(vis_order):
l,r=left[u],right[u]
if(l==0 and r==0):
dp[u]=1
else:
dp[u]=(dp[l]+dp[r]+3)%mod
#preorder(1,0)
res[1]=dp[1]
stack=[1]
while(stack):
u=stack.pop()
l,r=left[u],right[u]
if(l==0 and r==0):
continue
if(l!=0):
res[l]=(dp[l]+res[u])%mod
stack.append(l)
if(r!=0):
res[r]=(dp[r]+res[u])%mod
stack.append(r)
print(" ".join(map(str,res[1:n+1])))
使二进制字符串字符交替的最少反转次数
首位放到最后和01变化的顺序不影响。因此先01变化,对长度为偶数的数列来说就够了。对奇数来说,考虑是否需要首位移动。首位移动到最后,相当于把字符串和自己拼一起,并以长度为n的窗口滑动。每次移动时减去前一位对cnt的贡献,加上新的一位对cnt的贡献。实时更新每个窗口的ans,取最小值。
class Solution:
def minFlips(self, s: str) -> int:
target="01"
n=len(s)
cnt=0
for i in range(n):
if(s[i]!=target[i%2]):
cnt+=1
ans=min(cnt,n-cnt)
s+=s
for i in range(1,n):
if(s[i-1]!=target[(i-1)%2]):
cnt-=1
if(s[i+n-1]!=target[(i+n-1)%2]):
cnt+=1
ans=min(ans,cnt,n-cnt)
return ans
print(Solution().minFlips("111000"))
2026.3.16
长度为 n 的开心字符串中字典序第 k 小的字符串
class Solution:
def getHappyString(self, n: int, k: int) -> str:
if(k>3*(1<<(n-1))):
return ""
ans=[]
def dfs(cur,step):
if(step==n):
ans.append(cur)
return
if(step==0):
dfs("a",step+1)
dfs("b",step+1)
dfs("c",step+1)
else:
if(cur[-1]!='a'):
dfs(cur+"a",step+1)
if(cur[-1]!='b'):
dfs(cur+"b",step+1)
if(cur[-1]!='c'):
dfs(cur+"c",step+1)
dfs("",0)
ans.sort()
return ans[k-1]
print(Solution().getHappyString(3,9))
字符串乘方
KMP.next[i]表示前i个数的最大公共前后缀的长度,也是在这一个位置失配时模式串的指针应该跳到的位置。
构建next数组,目标串(模式串)指针在i=0,模式串指针在j=-1.同样可以使用KMP的移动规则,每次两个指针前移一位并记录next[i],如果失配j就往回跳,一位都不对跳到-1自然从头开始。
找循环节,最小循环节长度=L-next[L]。

while(True):
s=input()
if(s=='.'):
break
n=len(s)
next=[-1]*(n+1)
i=0
j=-1
while(i<n):
if(j==-1 or s[i]==s[j]):
i+=1
j+=1
next[i]=j
else:
j=next[j]
l=n-next[n]
if(n%l==0):
print(n//l)
else:
print(1)
2026.3.17
倒排索引查询
一个集合记录包含所有需要数的杂志,一个集合记录所有包含不需要数的杂志,最后两集合作差集即可。 不能一边读一边进行集合运算,否则前一步不需要的杂志后一步可能又加回来。 a(需要)集合初始化为第一个符合的集合,注意要set()复制一份而不要直接取引用,否则会把原数据修改。
n=int(input())
files=[]
for i in range(n):
t=list(map(int,input().split()))
files.append(set(t[1:]))
m=int(input())
for i in range(m):
q=list(map(int,input().split()))
a=set(files[q.index(1)])
b=set()
for j in range(n):
if(q[j]==1):
a&=files[j]
elif(q[j]==-1):
b|=files[j]
c=a-b
if(len(c)==0):
print("NOT FOUND")
else:
print(" ".join(map(str,sorted(c))))
编程填空:学生信息处理程序
输入逗号分隔的整数:
getline(cin,line);
stringstream ss(line);
string token;
getline(ss,name,',');
getline(ss, token, ',');
age = stoi(token);
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <cstdlib>
using namespace std;
class Student {
private:
string name;
int age;
int id;
int scores[5];
double avg=0;
public:
void input(){
string line;
int idx=0;
getline(cin,line);
stringstream ss(line);
string token;
getline(ss,name,',');
getline(ss, token, ',');
age = stoi(token);
getline(ss, token, ',');
id = stoi(token);
for(int i = 0; i < 4; i++) {
getline(ss, token, ',');
scores[i] = stoi(token);
}
}
void calculate(){
for(int i=0;i<4;i++){
avg+=scores[i];
}
avg/=4;
}
void output(){
cout<<name<<','<<age<<','<<id<<','<<avg<<endl;
}
};
int main() {
Student student; // 定义类的对象
student.input(); // 输入数据
student.calculate(); // 计算平均成绩
student.output(); // 输出数据
}
Complex类的成员函数
输入带分隔符的数还可以使用sscanf.sscanf(s,"%lf+%lfi",&r,&i);
重载运算符的基本语法。
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Complex {
private:
double r,i;
public:
void Print() {
cout << r << "+" << i << "i" << endl;
}
Complex& operator=(const char*s){
sscanf(s,"%lf+%lfi",&r,&i);
return *this;
}
// 在此处补充你的代码
};
int main() {
Complex a;
a = "3+4i"; a.Print();
a = "5+6i"; a.Print();
return 0;
}
2026.3.19
3维1-median近似
随机选取中心点c,向外划分64个环,每个环取m个点,并将每个点的权重定为card(ring[i])/m.计算选取出的所有点到q的距离即可。 注意long long范围是2^64,约1e18,因此求距离时每个维度坐标之差先换成double.
#include<bits/stdc++.h>
using namespace std;
struct Point{
long long x,y,z;
};
double dist(Point a,Point b){
double x0=a.x-b.x;
double y0=a.y-b.y;
double z0=a.z-b.z;
double ans=x0*x0+y0*y0+z0*z0;
return sqrt(ans);
}
struct Sample{
Point point;
double weight;
};
Point p[100005];
int main(){
int n,q;
scanf("%d %d",&n,&q);
for(int i=0;i<n;i++){
scanf("%lld %lld %lld",&p[i].x,&p[i].y,&p[i].z);
}
minstd_rand gen;
int c=int(double(gen())/gen.max()*n);
double tot=0;
for(int i=0;i<n;i++){
tot+=dist(p[i],p[c]);
}
double r0=tot*0.2/n;
vector<Point> rings[64];
for(int i=0;i<n;i++){
double d=dist(p[i],p[c]);
if(d<=r0){
rings[0].push_back(p[i]);
}
else{
int idx=int(log2(d/r0))+1;
if(idx>=64) idx=63;
rings[idx].push_back(p[i]);
}
}
int m=150;
vector<Sample> res;
for(int i=0;i<64;i++){
if(rings[i].size()==0) continue;
else if(rings[i].size()<=m){
for(int j=0;j<rings[i].size();j++){
res.push_back({rings[i][j],1.0});
}
}
else{
shuffle(rings[i].begin(),rings[i].end(),gen);
for(int j=0;j<m;j++){
res.push_back({rings[i][j],double(rings[i].size())/m});
}
}
}
for(int i=0;i<q;i++){
Point q0;
scanf("%lld %lld %lld",&q0.x,&q0.y,&q0.z);
double ans=0;
for(int j=0;j<res.size();j++){
Point p0=res[j].point;
double w=res[j].weight;
ans+=dist(p0,q0)*w;
}
printf("%lf\n",ans);
}
}
Apple
1.static类型:整个类共有,可以用类::来访问。
2.动态内存分配:Apple * p = new Apple[4];在堆上开辟了四块连续的空间,会调用默认构造函数。需要手动执行delete[] p;可以p[0]、p[1]访问。
静态/栈上分配:Apple p[4];。
3.拷贝构造函数:使用类成员时定义拷贝规则。
4.析构函数:删除指针时定义操作。
#include <iostream>
using namespace std;
class Apple {
// 在此处补充你的代码
public:
static int nTotalNumber;
Apple(){
nTotalNumber++;
}
Apple(const Apple &a){
}
~Apple(){
nTotalNumber--;
}
static void PrintTotal() {
cout << nTotalNumber << endl;
}
};
int Apple::nTotalNumber = 0;
Apple Fun(const Apple & a) {
a.PrintTotal();
return a;
}
int main()
{
Apple * p = new Apple[4];
Fun(p[2]);//4->3
Apple p1,p2;
Apple::PrintTotal ();//5
delete [] p;
p1.PrintTotal ();//1
return 0;
}
返回什么才好呢
1.参数默认值A(int x=123){val=x;}中,如果不传参则默认val为123,如果传参则val为传入的参数。
2.返回值类型:A&,可以修改原对象。
3.隐式类型转换:a.getObj()=n,隐式转换为A(n).
#include <iostream>
using namespace std;
class A {
public:
int val;
A(int x=123){
val=x;
}
A& GetObj(){
return *this;
}
// 在此处补充你的代码
};
int main()
{
int m,n;
A a;
cout << a.val << endl;
while(cin >> m >> n) {
a.GetObj() = m;
cout << a.val << endl;
a.GetObj() = A(n);
cout << a.val<< endl;
}
return 0;
}
奇怪的类复制

#include <iostream>
using namespace std;
class Sample {
public:
int v;
Sample(int x=0){
v=x;
}
Sample(const Sample &a){
this->v=a.v+2;
}
// 在此处补充你的代码
};
void PrintAndDouble(Sample o)
{
cout << o.v;
cout << endl;
}
int main()
{
Sample a(5);
Sample b = a;
PrintAndDouble(b);//9
Sample c = 20;
PrintAndDouble(c);//22
Sample d;
d = a;
cout << d.v;//5
return 0;
}
Big & Base 封闭类问题
初始化列表Big(int n):v(n),b(n):令v=n,b=n(b为base类型,会寻找匹配int类型的构造函数,因此相当于b.k=n)
没有默认构造的情况下需要初始化列表。
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
int k;
Base(int n):k(n) { }
};
class Big
{
public:
int v;
Base b;
Big(int n):v(n),b(n){
}
// 在此处补充你的代码
};
int main()
{
int n;
while(cin >>n) {
Big a1(n);
Big a2 = a1;
cout << a1.v << "," << a1.b.k << endl;
cout << a2.v << "," << a2.b.k << endl;
}
}
2026.3.21
子字符串的最优划分
class Solution:
def partitionString(self, s: str) -> int:
ans=1
a=set()
n=len(s)
for i in range(n):
if(s[i] in a):
ans+=1
a=set()
a.add(s[i])
return ans
2026.3.23
魔兽世界之一:备战
1.C++数组赋值,需另外建新数组,然后copy.copy(begin(red_seq),end(red_seq),red.sequence);
2.对类内赋值,声明后需要再引用。
3.printf不能传string,可以string.c_str().
#include<bits/stdc++.h>
using namespace std;
class Warrior{
public:
string name;
int life;
};
class Headquarter{
public:
string name;
int warriors[5] = {0};
static Warrior warrior_list[5];
int sequence[5];
int warrior_cnt=0;
int idx=0;
int life_sum=0;
Headquarter(){
warrior_list[0].name="dragon";
warrior_list[1].name="ninja";
warrior_list[2].name="iceman";
warrior_list[3].name="lion";
warrior_list[4].name="wolf";
}
static void input_cost(){
for(int i=0;i<5;i++) scanf("%d",&warrior_list[i].life);
}
bool make_warrior(int time){
int temp=0;
while(life_sum<warrior_list[sequence[idx]].life && temp<5){
idx++;
temp++;
if(idx==5) idx=0;
}
if(temp==5){
printf("%03d %s headquarter stops making warriors\n",time,name.c_str());
return false;
}
warrior_cnt++;
int num=sequence[idx];
warriors[num]++;
life_sum-=warrior_list[num].life;
printf("%03d %s %s %d born with strength %d,%d %s in %s headquarter\n",time,name.c_str(),warrior_list[num].name.c_str(),warrior_cnt,warrior_list[num].life,warriors[num],warrior_list[num].name.c_str(),name.c_str());
idx++;
if(idx==5) idx=0;
return true;
}
};
Warrior Headquarter::warrior_list[5];
int main(){
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
int M;
scanf("%d",&M);
Headquarter::input_cost();
Headquarter red,blue;
red.name="red";
blue.name="blue";
red.life_sum=M;
blue.life_sum=M;
int red_seq[5]={2,3,4,1,0};
int blue_seq[5]={3,0,1,2,4};
copy(begin(red_seq),end(red_seq),red.sequence);
copy(begin(blue_seq),end(blue_seq),blue.sequence);
printf("Case:%d\n",i);
bool flag1=true,flag2=true;
int time=0;
while(flag1||flag2){
if(flag1){
flag1=red.make_warrior(time);
}
if(flag2){
flag2=blue.make_warrior(time);
}
time++;
}
}
}
2026.3.23
统计 X 和 Y 频数相等的子矩阵数量
class Solution:
def numberOfSubmatrices(self, grid: list[list[str]]) -> int:
m=len(grid)
n=len(grid[0])
a=[[0 for _ in range(n+1)]for _ in range(m+1)]
check=[[0 for _ in range(n+1)]for _ in range(m+1)]
def trans(x):
if(x=="X"):
return 1
elif(x=="Y"):
return -1
return 0
for i in range(m):
for j in range(n):
a[i+1][j+1]=a[i][j+1]+a[i+1][j]+trans(grid[i][j])-a[i][j]
check[i+1][j+1]=check[i][j+1]|check[i+1][j]|abs(trans(grid[i][j]))
ans=0
for i in range(1,m+1):
for j in range(1,n+1):
if(check[i][j] and a[i][j]==0):
ans+=1
return ans
2026.3.24
中序表达式转后序表达式
Shunting Yard调度场算法。建立答案栈和符号栈,根据运算规则存入弹出符号。

n=int(input())
val={"+":1,"-":1,"*":2,"/":2}
for _ in range(n):
s=input()
num=""
ans=[]
sign=[]
for i in s:
if(i.isdigit() or i=='.'):
num+=i
else:
if(num!=""):
ans.append(num)
num=""
if(i=="("):
sign.append(i)
elif(i==')'):
while(sign and sign[-1]!="("):
temp=sign[-1]
sign.pop()
ans.append(temp)
sign.pop()
elif(i in "+-*/"):
while(sign and sign[-1] in "+-*/" and val[sign[-1]]>=val[i]):
temp=sign[-1]
sign.pop()
ans.append(temp)
sign.append(i)
if(num!=""):
ans.append(num)
while(sign):
ans.append(sign.pop())
print(" ".join(ans))
LRU 缓存
思路:
要求查找和插入都O(1),使用哈希表。要求灵活将内容移到队尾与删除队首,使用双向链表。 也可以使用Python内置的ordered_dict完成,有move_to_end()和popitem(last=False)模块。
代码
class Node:
def __init__(self,key=0,val=0):
self.key=key
self.val=val
self.prev=None
self.next=None
class LRUCache:
def __init__(self, capacity: int):
self.cache=dict()
self.capacity=capacity
self.head=Node()
self.tail=Node()
self.head.next=self.tail
self.tail.prev=self.head
def get(self, key: int) -> int:
if(key not in self.cache):
return -1
node=self.cache[key]
self.remove_node(node)
self.add_to_end(node)
return node.val
def put(self, key: int, value: int) -> None:
if(key in self.cache):
node=self.cache[key]
node.val=value
self.remove_node(node)
self.add_to_end(node)
else:
node=Node(key,value)
self.cache[key]=node
self.add_to_end(node)
if(len(self.cache)>self.capacity):
self.cache.pop(self.head.next.key)
self.remove_node(self.head.next)
def remove_node(self,node):
node.prev.next=node.next
node.next.prev=node.prev
def add_to_end(self,node):
node.prev=self.tail.prev
node.prev.next=node
node.next=self.tail
self.tail.prev=node
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.od=OrderedDict()
self.capacity=capacity
def get(self, key: int) -> int:
if(key not in self.od):
return -1
self.od.move_to_end(key)
return self.od[key]
def put(self, key: int, value: int) -> None:
if(key in self.od):
self.od.move_to_end(key)
self.od[key]=value
if(len(self.od)>self.capacity):
self.od.popitem(last=False)
[USACO12MAR] Flowerpot S
思路:
滑动窗口+单调队列。把所有点按x坐标排序,易知右侧点的left必定比左侧点的left大。因此可以使用滑动窗口,同时使用两个单调队列分别维护段中的最大值与最小值,每次的新值加入队尾并保持递增/递减,最值从队头取,老值从队头删除。
代码
from collections import deque
n,d=map(int,input().split())
rain=[]
for i in range(n):
t=list(map(int,input().split()))
rain.append(t)
rain=sorted(rain,key=lambda x:x[0])
maxq=deque()
minq=deque()
left=0
ans=float("INF")
for i in range(n):
while(maxq and rain[maxq[-1]][1]<=rain[i][1]):
maxq.pop()
maxq.append(i)
while(minq and rain[minq[-1]][1]>=rain[i][1]):
minq.pop()
minq.append(i)
while(rain[maxq[0]][1]-rain[minq[0]][1]>=d and left<i):
ans=min(ans,rain[i][0]-rain[left][0])
if(maxq[0]==left):
maxq.popleft()
if(minq[0]==left):
minq.popleft()
left+=1
if(ans==float("INF")):
print(-1)
else:
print(ans)
河中跳房子
二分答案。删点可以一路贪心往前,如果距离比当前距离近就右边向右,否则左边右边同时向右。
L,n,m=map(int,input().split())
a=[0]
for i in range(n):
t=int(input())
a.append(t)
a.append(L)
l=0
r=L
ans=0
while(l<=r):
mid=(l+r)>>1
cnt=0
cur=0
for i in range(1,n+2):
if(a[i]-a[cur]<mid):
cnt+=1
else:
cur=i
if(cnt>m):
r=mid-1
else:
ans=max(ans,mid)
l=mid+1
print(ans)
2026.3.25
垂直翻转子矩阵
class Solution:
def reverseSubmatrix(self, grid: list[list[int]], x: int, y: int, k: int) -> list[list[int]]:
m=len(grid)
n=len(grid[0])
i=x
j=x+k-1
while(i<j):
grid[i][y:y+k],grid[j][y:y+k]=grid[j][y:y+k],grid[i][y:y+k]
i+=1
j-=1
return grid
print(Solution().reverseSubmatrix([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],1,0,3))
矩阵的最大非负积
最大非负积->最大值与最小值dp
class Solution:
def maxProductPath(self, grid: list[list[int]]) -> int:
m=len(grid)
n=len(grid[0])
dp_max=[[-1 for _ in range(n)]for _ in range(m)]
dp_min=[[-1 for _ in range(n)]for _ in range(m)]
dp_max[0][0]=grid[0][0]
dp_min[0][0]=grid[0][0]
for i in range(1,m):
dp_min[i][0]=dp_min[i-1][0]*grid[i][0]
dp_max[i][0]=dp_max[i-1][0]*grid[i][0]
for i in range(1,n):
dp_min[0][i]=dp_min[0][i-1]*grid[0][i]
dp_max[0][i]=dp_max[0][i-1]*grid[0][i]
for i in range(1,m):
for j in range(1,n):
dp_min[i][j]=min(dp_min[i-1][j]*grid[i][j],dp_max[i-1][j]*grid[i][j],dp_min[i][j-1]*grid[i][j],dp_max[i][j-1]*grid[i][j])
dp_max[i][j]=max(dp_min[i-1][j]*grid[i][j],dp_max[i-1][j]*grid[i][j],dp_min[i][j-1]*grid[i][j],dp_max[i][j-1]*grid[i][j])
t=dp_max[m-1][n-1]
mod=10**9+7
if(t<0):
return -1
else:
return t%mod
print(Solution().maxProductPath([[-1,-2,-3],[-2,-3,-3],[-3,-3,-2]]))
判断矩阵经轮转后是否一致
class Solution:
def rotate(self,mat):
n=len(mat)
for i in range(1,n):
for j in range(i):
mat[i][j],mat[j][i]=mat[j][i],mat[i][j]
for i in range(n):
for j in range(n//2):
mat[i][j],mat[i][n-j-1]=mat[i][n-j-1],mat[i][j]
return mat
def findRotation(self, mat: list[list[int]], target: list[list[int]]) -> bool:
for i in range(4):
if(mat==target):
return True
self.rotate(mat)
return False
2026.3.26
今日化学论文
a=input()
s=[]
n=len(a)
t=""
for i in a:
if(i=="["):
if(t!=""):
s.append(t)
t=""
s.append(i)
elif(i.isdigit()):
t+=i
elif(i=="]"):
tmp=""
while(s and not s[-1].isdigit()):
tmp=s[-1]+tmp
s.pop()
tmp=tmp*int(s[-1])
s.pop()
s.pop()
s.append(tmp)
else:
if(t!=""):
s.append(t)
t=""
s.append(i)
ans=""
while(s):
ans=s[-1]+ans
s.pop()
print(ans)
k-heavyhitter
使用count-min sketch,分别五次哈希把n个数映到m个位置。每次存储当前n个数的k-heavyhitter,并在n为2的幂的时候清理。
#include "streaming.h"
using namespace std;
typedef unsigned long long u64;
#define mix(h) ({ \
(h) ^= (h) >> 23; \
(h) *= 0x2127599bf4325c37ULL; \
(h) ^= (h) >> 47; })
u64 fasthash64(u64 v, u64 seed) {
const uint64_t m = 0x880355f21e6d1965ULL;
u64 h = seed;
h ^= mix(v);
h *= m;
return mix(h);
}
int k,n;
set<int> res;
int cols=1000;
void init(int _k) {
k=_k;
n=0;
res.clear();
for(int i=0;i<5000;i++) Set(i,0);
}
void add(int x) {
n++;
int minm=1e9;
for(int i=0;i<5;i++){
u64 h=fasthash64(x,i);
int pos=i*cols+h%cols;
int temp=Get(pos);
temp++;
Set(pos,temp);
minm=min(minm,temp);
}
if((long long)minm*k>=n){
res.insert(x);
}
if((n&(n-1))==0){
for(auto it=res.begin();it!=res.end();){
int minm=1e9;
int x=*it;
for(int i=0;i<5;i++){
u64 h=fasthash64(x,i);
int pos=i*cols+h%cols;
int temp=Get(pos);
minm=min(minm,temp);
}
if(minm*k<n){
it=res.erase(it);
}
else{
it++;
}
}
}
}
vector <int> report() {
vector<int> ans;
for(int i:res){
ans.push_back(i);
}
return ans;
}
2026.3.29
简单计算器
顺序同中序转后序表达式,然后使用计算波兰表达式的方法。
a=list(input().split())
s1=[]
s2=[]
dic={"+":1,"-":1,"*":2,"/":2}
def cal(x,y,t):
x=float(x)
y=float(y)
if(t=="+"):
return x+y
elif(t=="-"):
return x-y
elif(t=="*"):
return x*y
elif(t=="/"):
return x/y
return 0
for i in a:
if(i.isdigit()):
s1.append(i)
else:
while(s2 and dic[i]<=dic[s2[-1]]):
t=s2.pop()
y=s1.pop()
x=s1.pop()
s1.append(cal(x,y,t))
s2.append(i)
while(s2):
y=s1.pop()
x=s1.pop()
t=s2.pop()
s1.append(cal(x,y,t))
print(f"{float(s1[-1]):.2f}")
A Knight’s Journey
t=int(input())
m,n=0,0
ans=""
dx=[-2,-1,1,2,2,1,-1,-2]
dy=[1,2,2,1,-1,-2,-2,-1]
def dfs(x,y,res,step):
global m,n,ans
if(step==m*n):
ans=min(ans,res)
return
for i in range(8):
xx=x+dx[i]
yy=y+dy[i]
if(0<=xx<m and 0<=yy<n and vis[xx][yy]==0):
vis[xx][yy]=1
dfs(xx,yy,res+a[xx][yy],step+1)
vis[xx][yy]=0
return
for qaq in range(t):
m,n=map(int,input().split())
a=[["" for _ in range(n)]for _ in range(m)]
vis=[[0 for _ in range(n)]for _ in range(m)]
for i in range(m):
for j in range(n):
a[i][j]=chr(ord("A")+j)+str(i+1)
ans="Z26"*26
vis[0][0]=1
dfs(0,0,"A1",1)
print(f"Scenario #{qaq+1}:")
if(ans=="Z26"*26):
print("impossible")
else:
print(ans)
print()
2026.3.30
等和矩阵分割 II
遍历每一行,并加入总和中。如果总和是数组和的一半,或者减去某个遍历过的数之后符合要求,则正确。删除上半部分的数可以由哈希表维护,把0加入表示不删除。删除下半部分即把数组倒过来。竖着分割即把数组转置。 转置的方法是先*grid解包,再zip. 注意特判只有一列的情况,此时只能删第一个或者分割线上的。第一行在处理完第一行后才能删,最后一行同理。
class Solution:
def canPartitionGrid(self, grid: list[list[int]]) -> bool:
m=len(grid)
n=len(grid[0])
sum=0
for i in range(m):
for j in range(n):
sum+=grid[i][j]
def check(a):
m=len(a)
n=len(a[0])
st=set()
st.add(0)
s=0
for i in range(m-1):
for j in range(n):
x=a[i][j]
s+=x
if(i>0 or j==0 or j==n-1):
st.add(x)
if(n==1):
if(s*2==sum or s*2==sum+a[0][0] or s*2==sum+a[i][0]):
return True
continue
if(s*2-sum in st):
return True
if(i==0):
st.update(a[i])
return False
return (check(grid) or check(grid[::-1]) or check(list(zip(*grid))) or check(list(zip(*grid))[::-1]))
print(Solution().canPartitionGrid([[1,4],[2,3]]))
解数独
二进制存储每行、列与九宫格的状态。 mask & (-mask):取出最低位的1,从最低位开始尝试。 digit = bin(digitMask).count(“0”) - 1:获得最低位的1是第几位。 mask &= (mask - 1):去掉最低位的1 启发式搜索:先把能唯一确定的格子填好,再对不确定的格子dfs. 注意dfs的时候如果成功了要传递状态并return掉,避免把好的结果覆盖掉。
class Solution:
def solveSudoku(self, board: list[list[str]]) -> None:
row=[0]*9
col=[0]*9
block=[[0 for _ in range(3)]for _ in range(3)]
spaces=[]
def flip(i,j,digit):
row[i]^=(1<<digit)
col[j]^=(1<<digit)
block[i//3][j//3]^=(1<<digit)
def dfs(step):
global valid
if(step==len(spaces)):
return True
i,j=spaces[step]
mask=(~(row[i]|col[j]|block[i//3][j//3]))&0x1ff
while(mask):
qaq=mask&(-mask)
digit=bin(qaq).count('0')-1
flip(i,j,digit)
board[i][j]=str(digit+1)
if(dfs(step+1)):
return True
flip(i,j,digit)
board[i][j]='.'
mask&=(mask-1)
return False
for i in range(9):
for j in range(9):
if(board[i][j]!='.'):
flip(i,j,int(board[i][j])-1)
while(True):
flag=False
for i in range(9):
for j in range(9):
if(board[i][j]=='.'):
mask=(~(row[i]|col[j]|block[i//3][j//3]))&0x1ff
if(not (mask&(mask-1))):
digit=bin(mask).count('0')-1
flip(i,j,digit)
board[i][j]=str(digit+1)
flag=True
if(not flag):
break
for i in range(9):
for j in range(9):
if(board[i][j]=='.'):
spaces.append((i,j))
dfs(0)
"""
Do not return anything, modify board in-place instead.
"""
board=[["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
Solution().solveSudoku(board)
for i in range(9):
for j in range(9):
print(board[i][j],end=" ")
print()
判断通过操作能否让字符串相等 II
class Solution:
def checkStrings(self, s1: str, s2: str) -> bool:
s11,s12,s21,s22=[],[],[],[]
n=len(s1)
for i in range(n):
if(i%2==0):
s11.append(s1[i])
s21.append(s2[i])
else:
s12.append(s1[i])
s22.append(s2[i])
s11.sort()
s12.sort()
s21.sort()
s22.sort()
if(s11==s21 and s12==s22):
return True
return False
2026.3.31
城堡问题
求连通块长度,而非递归深度。因此每次搜到一块就加一。
m=int(input())
n=int(input())
a=[]
dx=[0,-1,0,1]
dy=[-1,0,1,0]
def dfs(x,y,step):
area=1
for i in range(4):
if((a[x][y]&(1<<i))==0):
xx=x+dx[i]
yy=y+dy[i]
if(0<=xx<m and 0<=yy<n and vis[xx][yy]==0):
vis[xx][yy]=1
area+=dfs(xx,yy,step+1)
return area
for i in range(m):
a.append(list(map(int,input().split())))
ans=0
max_res=0
vis=[[0 for _ in range(n)]for _ in range(m)]
for i in range(m):
for j in range(n):
if(vis[i][j]==0):
vis[i][j]=1
max_res=max(max_res,dfs(i,j,1))
ans+=1
print(ans)
print(max_res)
字典序最小的生成字符串
class Solution:
def generateString(self, str1: str, str2: str) -> str:
n=len(str1)
m=len(str2)
a=['?']*(n+m-1)
for i in range(n):
if(str1[i]=='T'):
for j in range(i,i+m):
if(a[j]!='?' and a[j]!=str2[j-i]):
return ""
a[j]=str2[j-i]
qaq=a.copy()
for i in range(n+m-1):
if(qaq[i]=='?'):
qaq[i]='a'
for i in range(n):
if(str1[i]=='F'):
if("".join(qaq[i:i+m])==str2):
for j in range(i+m-1,i-1,-1):
if('?' not in a[i:i+m]):
return ""
if(a[j]=="?"):
qaq[j]='b'
break
return "".join(qaq)
print(Solution().generateString("TTFFT","fff"))
MyString

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class MyString {
char * p;
public:
MyString(const char * s) {
if( s) {
p = new char[strlen(s) + 1];
strcpy(p,s);
}
else
p = NULL;
}
~MyString() { if(p) delete [] p; }
// 在此处补充你的代码
//拷贝构造,MyString s2=s1
MyString(const MyString &s){
if(s.p){
p = new char[strlen(s.p) + 1];
strcpy(p,s.p);
}
else p=NULL;
}
//运算符重载 s2=s1(MyString)
MyString &operator=(const MyString &s){
if(this!=&s){
if(p) delete []p;
if(s.p){
p=new char[strlen(s.p)+1];
strcpy(p,s.p);
}
else p=NULL;
}
return *this;
}
//运算符重载 s2=w2(char*)
MyString &operator=(const char*s){
if(p) delete []p;
if(s){
p=new char[strlen(s)+1];
strcpy(p,s);
}
else p=NULL;
return *this;
}
//s3.Copy(w1)
void Copy(const char*s){
*this=s;
}
//cout<<
friend ostream &operator<<(ostream &os,const MyString &s){
if(s.p) os<<s.p;
return os;
}
};
int main()
{
char w1[200],w2[100];
while( cin >> w1 >> w2) {
MyString s1(w1),s2 = s1;
MyString s3(NULL);
s3.Copy(w1);
cout << s1 << "," << s2 << "," << s3 << endl;
s2 = w2;
s3 = s2;
s1 = s3;
cout << s1 << "," << s2 << "," << s3 << endl;
}
}
看上去好坑的运算符重载
类型重载。operator int()

#include <iostream>
using namespace std;
class MyInt
{
int nVal;
public:
MyInt( int n) { nVal = n ;}
// 在此处补充你的代码
MyInt & operator-(int n){
nVal-=n;
return *this;
}
operator int(){
return nVal;
}
};
int Inc(int n) {
return n + 1;
}
int main () {
int n;
while(cin >>n) {
MyInt objInt(n);
objInt-2-1-3;
cout << Inc(objInt);
cout <<",";
objInt-2-1;
cout << Inc(objInt) << endl;
}
return 0;
}
惊呆!Point竟然能这样输入输出
流运算符重载。输入Point可修改,输出为const.
#include <iostream>
using namespace std;
class Point {
private:
int x;
int y;
public:
Point() { };
// 在此处补充你的代码
friend istream &operator>>(istream &is,Point &p){
is>>p.x>>p.y;
return is;
}
friend ostream &operator<<(ostream &os,const Point &p){
os<<p.x<<","<<p.y;
return os;
}
};
int main()
{
Point p;
while(cin >> p) {
cout << p << endl;
}
return 0;
}
二维数组类
memcpy:
[]:重载,返回一整行,然后用[j]来定位。
():定位到某一个数
#include <iostream>
#include <cstring>
using namespace std;
class Array2 {
private:
int r,c;
int *p;
public:
Array2(int _r=0,int _c=0):r(_r),c(_c) {
if(r*c>0) p=new int[r*c];
else p=NULL;
}
~Array2(){
if(p) delete []p;
}
Array2(const Array2 &a){
r=a.r;
c=a.c;
if(r*c>0){
p=new int[r*c];
memcpy(p,a.p,sizeof(int)*r*c);
}
else p=NULL;
}
Array2 &operator=(const Array2 &a){
if(this!=&a){
if(p) delete []p;
r=a.r;
c=a.c;
if(r*c>0){
p=new int[r*c];
memcpy(p,a.p,sizeof(int)*r*c);
}
else p=NULL;
}
return *this;
}
int* operator[](int i){
return p+i*c;
}
int& operator()(int i,int j){
return p[i*c+j];
}
// 在此处补充你的代码
};
int main() {
Array2 a(3,4);
int i,j;
for( i = 0;i < 3; ++i )
for( j = 0; j < 4; j ++ )
a[i][j] = i * 4 + j;
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << a(i,j) << ",";
}
cout << endl;
}
cout << "next" << endl;
Array2 b; b = a;
for( i = 0;i < 3; ++i ) {
for( j = 0; j < 4; j ++ ) {
cout << b[i][j] << ",";
}
cout << endl;
}
return 0;
}
别叫,这个大整数已经很简化了!
选择friend:1.非类内函数访问private内容
2.对称性转换
3.左操作数不是类对象
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int MAX = 110;
class CHugeInt {
// 在此处补充你的代码
private:
int digits[210];
int len;
public:
CHugeInt(const char *s){
memset(digits,0,sizeof(digits));
len=strlen(s);
for(int i=0;i<len;i++){
digits[i]=s[len-i-1]-'0';
}
}
CHugeInt(int n){
memset(digits,0,sizeof(digits));
if(n==0) len=1;
else{
len=0;
while(n>0){
digits[len++]=n%10;
n/=10;
}
}
}
friend CHugeInt operator+(const CHugeInt &a,const CHugeInt &b){
CHugeInt res(0);
res.len=0;
int carry=0;
int max_len=max(a.len,b.len);
for(int i=0;i<max_len||carry;i++){
int sum=a.digits[i]+b.digits[i]+carry;
res.digits[i]=sum%10;
carry=sum/10;
res.len++;
}
// if(carry){
// res.digits[max_len++]=carry;
// }
return res;
}
CHugeInt& operator+=(const CHugeInt &n){
*this=*this+n;
return *this;
}
CHugeInt& operator++(){
*this+=1;
return *this;
}
CHugeInt operator++(int){
CHugeInt temp=*this;
*this+=1;
return temp;
}
friend ostream& operator<<(ostream &os,const CHugeInt &a){
for(int i=a.len-1;i>=0;i--){
os<<a.digits[i];
}
return os;
}
};
int main()
{
char s[210];
int n;
while (cin >> s >> n) {
CHugeInt a(s);
CHugeInt b(n);
cout << a + b << endl;
cout << n + a << endl;
cout << a + n << endl;
b += n;
cout << ++ b << endl;
cout << b++ << endl;
cout << b << endl;
}
return 0;
}
全面的MyString
#include <cstdlib>
#include <iostream>
using namespace std;
int strlen(const char * s)
{ int i = 0;
for(; s[i]; ++i);
return i;
}
void strcpy(char * d,const char * s)
{
int i = 0;
for( i = 0; s[i]; ++i)
d[i] = s[i];
d[i] = 0;
}
int strcmp(const char * s1,const char * s2)
{
for(int i = 0; s1[i] && s2[i] ; ++i) {
if( s1[i] < s2[i] )
return -1;
else if( s1[i] > s2[i])
return 1;
}
return 0;
}
void strcat(char * d,const char * s)
{
int len = strlen(d);
strcpy(d+len,s);
}
class MyString
{
private:
char *p;
public:
MyString(const char *s=""){
if(s){
p=new char[strlen(s)+1];
strcpy(p,s);
}
else p=NULL;
}
~MyString(){
if(p) delete []p;
}
MyString(const MyString &s){
if(s.p){
p=new char[strlen(s.p)+1];
strcpy(p,s.p);
}
else p=NULL;
}
MyString& operator=(const MyString &s){
if(this!=&s){
if(p) delete []p;
if(s.p){
p=new char[strlen(s.p)+1];
strcpy(p,s.p);
}
else p=NULL;
}
return *this;
}
MyString& operator=(const char*s){
if(p) delete []p;
if(s){
p=new char[strlen(s)+1];
strcpy(p,s);
}
else p=NULL;
return *this;
}
friend MyString operator+(const MyString &s,const MyString &t){
MyString res("");
res.p=new char[strlen(s.p)+strlen(t.p)+1];
strcpy(res.p,s.p);
strcat(res.p,t.p);
return res;
}
MyString& operator+=(const MyString &s){
*this=*this+s;
return *this;
}
friend bool operator>(const MyString &s,const MyString &t){
return strcmp(s.p,t.p)>0;
}
friend bool operator<(const MyString &s,const MyString &t){
return strcmp(s.p,t.p)<0;
}
friend bool operator==(const MyString &s,const MyString &t){
return strcmp(s.p,t.p)==0;
}
char & operator[](int i){
return p[i];
}
MyString operator()(int pos,int len){
MyString res("");
res.p=new char[len+1];
for(int i=0;i<len;i++){
res.p[i]=p[pos+i];
}
res.p[len]=0;
return res;
}
friend ostream &operator<<(ostream &os,const MyString &s){
if(s.p) os<<s.p;
return os;
}
// 在此处补充你的代码
};
int CompareString( const void * e1, const void * e2)
{
MyString * s1 = (MyString * ) e1;
MyString * s2 = (MyString * ) e2;
if( * s1 < *s2 )
return -1;
else if( *s1 == *s2)
return 0;
else if( *s1 > *s2 )
return 1;
}
int main()
{
MyString s1("abcd-"),s2,s3("efgh-"),s4(s1);
MyString SArray[4] = {"big","me","about","take"};
cout << "1. " << s1 << s2 << s3<< s4<< endl;
s4 = s3;
s3 = s1 + s3;
cout << "2. " << s1 << endl;
cout << "3. " << s2 << endl;
cout << "4. " << s3 << endl;
cout << "5. " << s4 << endl;
cout << "6. " << s1[2] << endl;
s2 = s1;
s1 = "ijkl-";
s1[2] = 'A' ;
cout << "7. " << s2 << endl;
cout << "8. " << s1 << endl;
s1 += "mnop";
cout << "9. " << s1 << endl;
s4 = "qrst-" + s2;
cout << "10. " << s4 << endl;
s1 = s2 + s4 + " uvw " + "xyz";
cout << "11. " << s1 << endl;
qsort(SArray,4,sizeof(MyString),CompareString);
for( int i = 0;i < 4;i ++ )
cout << SArray[i] << endl;
//s1的从下标0开始长度为4的子串
cout << s1(0,4) << endl;
//s1的从下标5开始长度为10的子串
cout << s1(5,10) << endl;
return 0;
}
继承自string的MyString
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class MyString:public string
{
// 在此处补充你的代码
public:
MyString():string(){}
MyString(const char *s):string(s){}
MyString(const string &s):string(s){}
MyString operator()(int pos,int len){
return this->substr(pos,len);
}
};
int main()
{
MyString s1("abcd-"),s2,s3("efgh-"),s4(s1);
MyString SArray[4] = {"big","me","about","take"};
cout << "1. " << s1 << s2 << s3<< s4<< endl;
s4 = s3;
s3 = s1 + s3;
cout << "2. " << s1 << endl;
cout << "3. " << s2 << endl;
cout << "4. " << s3 << endl;
cout << "5. " << s4 << endl;
cout << "6. " << s1[2] << endl;
s2 = s1;
s1 = "ijkl-";
s1[2] = 'A' ;
cout << "7. " << s2 << endl;
cout << "8. " << s1 << endl;
s1 += "mnop";
cout << "9. " << s1 << endl;
s4 = "qrst-" + s2;
cout << "10. " << s4 << endl;
s1 = s2 + s4 + " uvw " + "xyz";
cout << "11. " << s1 << endl;
sort(SArray,SArray+4);
for( int i = 0;i < 4;i ++ )
cout << SArray[i] << endl;
//s1的从下标0开始长度为4的子串
cout << s1(0,4) << endl;
//s1的从下标5开始长度为10的子串
cout << s1(5,10) << endl;
return 0;
}
DISCUSSION
Comments
Sign in with GitHub to join the conversation.