int heap[MXN],sz=0; void push(int x){ int i=sz++;//自已节点的编号 while(i>0){ int p=(i-1)/2;//父亲节点的编号 if(heap[p]<=x)break;//如果已经没有大小颠倒则退出 heap[i]=heap[p];//父亲节点放下来,自已提上去 i=p; } heap[i]=x; } int pop(){ int ret=heap[0];//最小值 int x=heap[--sz];//要提到根的数值 int i=0;//从根开始向下交换 while(i*2+1<sz){ int a=i*2+1,b=i*2+2;//比较儿子的值 if(b<sz&&heap[b]<heap[a]) a=b; if(heap[a]>=x) break;//如果已经没有大小颠倒则退出 heap[i]=heap[a];//把儿子的数值提上来 i=a; } heap[i]=x; return ret; }
题目大意:奶牛们刚刚在丛林里抢了一辆卡车。由于奶牛们的驾驶技术不高,卡车的油箱被刮漏了。现在油箱里有P(1 ≤ P ≤ 1,000,000)单位的油,每行驶一个单位,油箱就损失一个单位的油。而最近的城镇离这里有L(1 ≤ L ≤ 1,000,000)单位。现在道路上有N(1 ≤ N ≤ 10,000)个加油站,每个加油站有两个信息:一是其距离城镇的距离,二是加油站能供应的油量。现在油箱的容量无限,加油站一定会将能供应的油全部供应。奶牛们认为丛林里很危险,决定在能到达城镇的前提下,停留尽量少的加油站。计算奶牛们至少要停靠几个加油站。如果它们无法到达城镇,输出-1。
解法:当燃料为0时,选择加油量最大的加油站
int L,P,N,M; int A[MXN+1],B[MXN+1]; void Fun(){ A[N]=L; B[N]=0; N++; priority_queue<int> que; int ans=0,pos=0,tank=P; for(int i=0;i<N;++i){ int d=A[i]-pos; while(tank-d<0){ if(que.empty()){ puts("-1"); return ; } tank+=que.top(); que.pop(); ans++; } tank-=d; pos=A[i]; que.push(B[i]); } printf("%d\n",ans); }
struct node{ int val; node *lch,*rch; }; node *insert(node *p,int x){ if(p==NULL){ node* q=new node; q->val=x; q->lch=q->rch=NULL; return q; } else{ if(x<p->val) p->lch=insert(p->lch,x); else p->rch=insert(p->rch,x); return p; } } bool find(node *p,int x){ if(p==NULL) return false; else if(x==p->val) return true; else if (x<p->val) return find(p->lch,x); else return find(p->rch,x); } node *remove(node *p,int x){ if(p== NULL) return NULL; else if(x<p->val) p->lch=remove(p->lch,x); else if(x>p->val) p->rch=remove(p->rch,x); else if(p->lch==NULL){ node *q=p->rch; delete p; return q; } else if(p->lch->rch==NULL){ node *q=p->lch; q->rch=p->rch; delete p; return q; } else{ node *q; for(q=p->lch;q->rch->rch!=NULL;q=q->rch); node *r=q->rch; q->rch=r->lch; r->lch=p->lch; r->rch=p->rch; delete p; return r; } return p; } node *root=NULL; root=insert(root,1); find(root,1);
使用set
int main(){ set<int> s; s.insert(3); set<int>::iterator ite; ite=s.find(1); if(ite==s.end()) puts("not found"); s.erase(3); if(s.count(3)!=0) puts("found"); }
使用map
int main(){ map<int,const char *> m; m.insert(make_pair(1,"ONE")); m.insert(make_pair(10,"TEN")); m[10]="TEd"; map<int,const char*>::iterator ite; ite=m.find(1); puts(ite->second); m.erase(1); }
int par[MXN];//父亲 int rank[MXN];//树的高度 void init(int n){ for(int i=0;i<n;++i){ par[i]=i; rank[i]=0; } } int find(int x){ if(par[x]==x){ return x; }else{ return par[x]=find(par[x]); } } void unite(int x,int y){ x=find(x); y=find(y); if(x==y) return ; if(rank[x]<rank[y]){ par[x]=y; }else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool same(int x,int y){ return find(x)==find(y); }
题意:
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。
解法:
每只动物i创建3个元素i-A,i-B,i-C,
i-x 表示i属于种类x,并查集的每一个组表示组内的元素要么同时发生,要么同时不发生
(1)x和y属于同一种,合并x-A和y-A,合并x-B和y-B,合并x-C和y-C.
(2)x吃y,合并x-A和y-B,合并x-B和y-C,合并x-C和y-A
int N,K; int T[MXK],X[MXK],Y[MXK]; void Fun(){ init(N*3);//元素x,x+N,X+2*N分别代表x-A,x-B,x-C int ans=0; for(int i=0;i<K;++i) { int t=T[i]; int x=X[i]-1,y=Y[i]-1;//输入变成0,...,N-1范围 if(x<0||N<=x||y<0||N<=y){ ans++; continue; } if(t==1){ if(same(x,y+N)||same(x,y+2*N)){//根据对称性只需判断(x-A,y-B)和(x-A,y-C) ans++; } else{ unite(x,y); unite(x+N,y+N); unite(x+N*2,y+N*2); } } else{ if(same(x,y)||same(x,y+2*N)){//根据对称性只需是否相同,存在反过来吃的情况 ans++; } else{ unite(x,y+N): unite(x+N,y+2*N); unite(x+2*N,y); } } } printf("%d\n",ans); }