code1:C++

include

include

include

int main() {
std::priority_queue pq;
std::string command;
int value;
while (std::cin >> command) {
if (command == "end") {
break;
} else if (command == "insert") {
std::cin >> value;
pq.push(value);
} else if (command == "extract") {
if (!pq.empty()) {
std::cout << pq.top() << std::endl;
pq.pop();
}
}
}

return 0;

}
解题思路:首先,利用C++标准库中的std::priority_queue来创建一个整数类型的最大堆优先队列。然后,程序进入一个循环,等待用户输入命令。用户可以通过输入"insert"后跟一个整数来向队列中插入元素;输入"extract"来提取并打印队列中优先级最高的元素(即最大元素),随后从队列中移除该元素。若用户输入"end",则循环终止,程序结束。整个过程展示了如何利用优先队列管理元素,根据优先级(本例中为数值大小)进行插入和提取操作。

code2:C++

include

include

include

using namespace std;
int f[100001][40],a,x,LC,n,m,p,len,l,r;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
f[i][0]=a;
}
LC=(int)(log(n)/log(2));
for(int j=1;j<=LC;j++)
for (int i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
p=(int)(log(r-l+1)/log(2));
printf("%d\n",max(f[l][p],f[r-(1<<p)+1][p]));
}
return 0;
}
解题思路:首先,读取数组长度n和查询次数m,然后读取数组a的元素。接着,利用稀疏表(Sparse Table)数据结构预处理数组,以便快速查询任意区间的最大值。稀疏表f的每一行j代表子数组长度为2^j时的最大值,通过递推关系填充稀疏表。最后,对于每个查询,计算查询区间长度对应的稀疏表索引p,并利用该索引在稀疏表中查找并输出查询区间的最大值。整个过程通过预处理减少了查询时间,实现了高效的区间最大值查询。

code3:c++

include

include

using namespace std;

template
class smallest_heap{
private:
item heap[10001];
int len;
public:
smallest_heap();
void push(item const &);
void pop();
item top();
int size();
bool empty();

};

template
smallest_heap::smallest_heap(){
len=0;
memset(heap,0,sizeof(heap));
}

template
void smallest_heap::push(item const &n){
heap[++len]=n;
int son=len,father=son/2;
while(heap[son]<heap[father] && father>=1){
swap(heap[son],heap[father]);
son=father,father=son/2;
}
}

template
void smallest_heap::pop(){
swap(heap[1],heap[len]);
heap[len--]=0;
int father=1,son=2;
while(son<=len){
if(son<len && heap[son]>heap[son+1]) son++;
if(heap[father]>heap[son]){
swap(heap[father],heap[son]);
father=son,son=father*2;
}else break;
}
}

template
item smallest_heap::top(){
return heap[1];
}

template
int smallest_heap::size(){
return len;
}

template
bool smallest_heap::empty(){
return len;
}

smallest_heap h;
int n,ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int a;
cin>>a;
h.push(a);
}
while(h.size()>1){
int x=h.top(); h.pop();
int y=h.top(); h.pop();
h.push(x+y);
ans+=x+y;
}
cout<<ans;
return 0;
}
解题思路:首先,定义一个最小堆(Min Heap)的数据结构模板,支持插入、删除堆顶、获取堆顶、获取堆大小和检查是否为空等操作。然后,读取一系列整数,将它们插入最小堆中。接着,通过不断从堆中取出两个最小元素(即堆顶元素和其后的最小元素),将它们相加后再插入堆中,并累加这两个元素的和。这个过程重复进行,直到堆中只剩下一个元素。最后,输出累加的和,这个和代表了所有取出元素对之和的总和。这种方法常用于处理需要频繁获取最小元素并合并的问题。

code4:C++

include

include

include

using namespace std;
const int ML=105;
int n,m;
int a[ML];
int main(){
scanf("%d %d",&n,&m);
int num=n,last=1;
while(num){
int cnt=0;
for(int i=last;cnt!=m;i++){
if(i>n) i%=n;
if(a[i]-1) continue;
++cnt;
if(cnt
m){
a[i]=-1;
num--;
last=i+1;
printf("%d ",i);
break;
}
}
}
return 0;
}
解题思路:模拟一个环形“打地鼠”游戏,其中n个地鼠站成一个圈,玩家每次可以连续打掉m个地鼠。程序使用一个数组a来记录每个位置的地鼠状态(初始时都为可打状态,但这里用-1表示已被打掉的地鼠可能不太直观,更常见的做法是用0或1表示)。然后,程序通过一个循环来模拟游戏过程,直到所有地鼠都被打掉。在每次循环中,程序从上一个被打掉地鼠的下一个位置开始,连续寻找m个未被打掉的地鼠,将它们标记为已打掉,并输出这些地鼠的编号。这个过程一直持续到没有地鼠可打为止。

code5:C++

include<bits/stdc++.h>

using namespace std;
int n,f[100010];
struct node{
int num;
int id;
}e;
deque q;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
while (!q.empty()&&q.back().num<a) f[q.back().id]=i,q.pop_back();
e.num=a; e.id=i;
q.push_back(e);
}
for (int i=1;i<=n;i++) printf("%d\n",f[i]);
return 0;
}
解题思路:利用双端队列(deque)维护一个单调递减的队列,以解决滑动窗口最大值问题。首先,读取一个整数n,表示有n个数。然后,对于每个数,如果它大于deque末尾的元素,则将该元素从deque中移除,直到deque为空或末尾元素大于等于当前数。这样做是为了保持deque的单调性。接着,将当前数和它的下标加入deque。最后,遍历deque,利用之前记录的下标信息,更新每个位置之前的最大值(即滑动窗口的最大值),并输出这些最大值。

code6:C++

include<bits/stdc++.h>

using namespace std;

namespace IO
{
const int S=(1<<20)+5;
//Input Correlation
char buf[S],H,T;
inline char Get()
{
if(HT) T=(H=buf)+fread(buf,1,S,stdin);
if(H
T) return -1;return H++;
}
inline int read()
{
int x=0;char c=Get();
while(!isdigit(c)) c=Get();
while(isdigit(c)) x=x
10+c-'0',c=Get();
return x;
}
//Output Correlation
char obuf[S],oS=obuf,oT=oS+S-1,c,qu[55];int qr;
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
inline void putc(char x){*oS++ =x;if(oS==oT) flush();}
template inline void print(I x)
{
if(!x) putc('0');
if(x<0) putc('-'),x=-x;
while(x) qu[++qr]=x%10+'0',x/=10;
while(qr) putc(qu[qr--]);
putc(' ');
}
}

using namespace IO;
typedef unsigned int uint;
const int N=200010;
struct Seg
{
uint l,r,id;
Seg(uint a=0,uint b=0,uint c=0):l(a),r(b),id(c){}
friend bool operator < (const Seg &a,const Seg &b){return a.l<b.l;}
} seg[N<<1];
int mul[19][N<<1];
int ans[N];
uint n,m;

void Init()
{
sort(seg+1,seg+1+2n);
int pr=0;
seg[2
n+1]=Seg(-1,-1);
for(int i=1;i<=2n;i++)
{
while(seg[pr+1].l<=seg[i].r) pr++;
mul[0][i]=pr;
}
for(int j=1;j<=18;j++)
for(int i=1;i<=2
n;i++)
mul[j][i]=mul[j-1][mul[j-1][i]];
seg[0]=Seg(-1,-1);
}

int main()
{
uint l,r;
n=read();m=read();
for(int i=1;i<=n;i++)
{
l=read();r=read();
if(l<=r)
{
seg[i]=Seg(l,r,i);
seg[n+i]=Seg(m+l,m+r);
}
else
{
seg[i]=Seg(l,m+r,i);
seg[n+i]=Seg(m+l,m2+r);
}
}
Init();
for(int i=1;i<=2
n;i++)
{
if(!seg[i].id) continue;
int p=i,res=2;
for(int j=18;j>=0;j--)
if(seg[mul[j][p]].r-seg[i].l<m)
p=mul[j][p],res+=1<<j;
ans[seg[i].id]=res;
}
for(int i=1;i<=n;i++) print(ans[i]);
flush();
return 0;
}
解题思路:利用倍增法预处理每个区间端点向右能延伸到的最远不相交区间的位置信息,以便快速回答查询。首先,将每个区间根据其左端点排序,并处理跨越数组中点的情况,将其拆分为两个区间。然后,使用倍增数组mul记录从每个位置开始,向右跳2^j步后所能到达的最远不相交区间的位置。最后,对于每个查询区间,通过倍增法快速找到其内部不相交区间的数量,并输出结果。这种方法结合了离线查询、排序和倍增法的思想,提高了查询效率。

posted on 2025-02-07 18:54  Penson2025cpc  阅读(13)  评论(0)    收藏  举报