题意:一只蚂蚁位与原点,在x轴正半轴上会不时地出现一些蛋糕,蚂蚁每次想吃蛋糕时选取最近的去吃,如果前后距离相同,则吃眼前的那一块(即方向为蚂蚁的正前),求最后蚂蚁行进距离。
思路:优先队列q存储蚂蚁前面的蛋糕(从小到大排),q2存储后面的(从大到小排),这样两队队首分别是前后离他最近的。
优先队列:
#include<iostream> #include<stdio.h> #include<queue> using namespace std; struct cmp1{ bool operator ()(int &a,int &b){ return a>b;//最小值优先 } }; priority_queue<int,vector<int>,cmp1>q;//从小到大 priority_queue<int>q2;//从大到小 int main(){ int T,L,n,A,B,i; int x,ans,t; int temp1,temp2; scanf("%d",&T); for(i=1;i<=T;++i){ scanf("%d%d",&L,&n); while(!q.empty())q.pop(); while(!q2.empty())q2.pop(); x=0;//初始位置 ans=0; t=1;//方向 while(n--){ scanf("%d",&A); if(A==0){ scanf("%d",&B); if(B>=x)q.push(B); else q2.push(B); } else{ if(!q.empty()&&!q2.empty()){ temp1=q.top(); temp2=q2.top(); if(temp1-x<x-temp2){ t=1; ans+=temp1-x; x=temp1; q.pop(); } else if(temp1-x>x-temp2){ t=-1; ans+=x-temp2; x=temp2; q2.pop(); } else if(t==1){ ans+=temp1-x; x=temp1; q.pop(); } else{ ans+=x-temp2; x=temp2; q2.pop(); } } else if(!q.empty()){ temp1=q.top(); t=1; ans+=temp1-x; x=temp1; q.pop(); } else if(!q2.empty()){ temp2=q2.top(); t=-1; ans+=x-temp2; x=temp2; q2.pop(); } } } printf("Case %d: %d ",i,ans); } return 0; }
线段树:
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAXN=100010; const int INF=0x3f3f3f3f; struct Node { int l,r; int t; int Min,Max; }segTree[MAXN*3]; void Build(int i,int l,int r) { segTree[i].l=l; segTree[i].r=r; segTree[i].t=0; if(l==r) { segTree[i].Min=INF; segTree[i].Max=-1; return; } int mid=(l+r)>>1; Build(i<<1,l,mid); Build((i<<1)|1,mid+1,r); segTree[i].Max=max(segTree[i<<1].Max,segTree[(i<<1)|1].Max); segTree[i].Min=min(segTree[i<<1].Min,segTree[(i<<1)|1].Min); } void add(int i,int t) { if(segTree[i].l==t&&segTree[i].r==t) { segTree[i].Max=segTree[i].Min=t; segTree[i].t++; return; } int mid=(segTree[i].l+segTree[i].r)>>1; if(t<=mid)add(i<<1,t); else add((i<<1)|1,t); segTree[i].Max=max(segTree[i<<1].Max,segTree[(i<<1)|1].Max); segTree[i].Min=min(segTree[i<<1].Min,segTree[(i<<1)|1].Min); } void del(int i,int t) { if(segTree[i].l==t&&segTree[i].r==t) { segTree[i].t--; if(segTree[i].t==0) { segTree[i].Min=INF; segTree[i].Max=-1; } return; } int mid=(segTree[i].l+segTree[i].r)>>1; if(t<=mid)del(i<<1,t); else del((i<<1)|1,t); segTree[i].Max=max(segTree[i<<1].Max,segTree[(i<<1)|1].Max); segTree[i].Min=min(segTree[i<<1].Min,segTree[(i<<1)|1].Min); } int query1(int i,int l,int r)//查询最大值 { if(segTree[i].l==l&&segTree[i].r==r) { return segTree[i].Max; } int mid=(segTree[i].l+segTree[i].r)>>1; if(r<=mid)return query1(i<<1,l,r); else if(l>mid) return query1((i<<1)|1,l,r); else return max(query1(i<<1,l,mid),query1((i<<1)|1,mid+1,r)); } int query2(int i,int l,int r)//查询最大值 { if(segTree[i].l==l&&segTree[i].r==r) { return segTree[i].Min; } int mid=(segTree[i].l+segTree[i].r)>>1; if(r<=mid)return query2(i<<1,l,r); else if(l>mid) return query2((i<<1)|1,l,r); else return min(query2(i<<1,l,mid),query2((i<<1)|1,mid+1,r)); } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int x; int T; int n; int m; int flag; scanf("%d",&T); int a,b; int iCase=0; while(T--) { iCase++; scanf("%d%d",&n,&m); Build(1,0,n); int flag=1;//往前的 x=0; int ans=0; while(m--) { scanf("%d",&a); if(a==0) { scanf("%d",&b); add(1,b); } else { int t1=query1(1,0,x); int t2=query2(1,x,n); if(t1==-1&&t2!=INF) { ans+=t2-x; x=t2; del(1,t2); flag=1; } else if(t1!=-1&&t2==INF) { ans+=x-t1; x=t1; del(1,t1); flag=-1; } else if(t1!=-1&&t2!=INF) { if(x-t1>t2-x) { ans+=t2-x; x=t2; del(1,t2); flag=1; } else if(x-t1<t2-x) { ans+=x-t1; x=t1; del(1,t1); flag=-1; } else { if(flag==1) { ans+=t2-x; x=t2; del(1,t2); flag=1; } else { ans+=x-t1; x=t1; del(1,t1); flag=-1; } } } } } printf("Case %d: %d ",iCase,ans); } return 0; }