A.http://acm.hdu.edu.cn/showproblem.php?pid=5437
思路:维护一个优先队列,模拟开门,枚举每一个人,同时记录当先开门的位置,如果人数等于开门位置,就从队列中取出min(size(),q),放到我们的答案队列中。注意开门时间可能相同,所以要先排序,再加一个循环。还有最后一次开门,剩下的人都放进来。注意他说的只有两次ni会超过10000,所以我们可以在输入时记下查询的最大位置。当答案队列中的人大于查询的最大位置就可以退出循环了,这样就不会超时了。因为代码找不到了,就不贴了。
B.http://acm.hdu.edu.cn/showproblem.php?pid=5438
思路:在输边的时候记录每个点的度数。然后一遍循环,bfs模拟删点。最后再tarjan求联通分量。这个地方可以考虑直接bfs求联通分量的点数应该更简单。
#include<cstdio> #include<iostream> #include<queue> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int MAXN=11000; const int MAXM=110000; struct Edge{ int v,nex; }edge[MAXM]; vector<int> G[MAXN]; ll value[MAXN]; int dfn[MAXN]; int low[MAXN]; int deg[MAXN]; int head[MAXN]; int stack[MAXN]; bool instack[MAXN]; int inde,top,block; vector<int> bblock[MAXN]; int T,p,m,u,v,tot; void addedge(int u,int v) { edge[tot].v=v; edge[tot].nex=head[u]; head[u]=tot++; } void bfs(int u) { int tmp; queue<int> que; que.push(u); while(!que.empty()) { tmp=que.front(); que.pop(); for(int i=0;i<G[tmp].size();i++) { v=G[tmp][i]; G[tmp][i]=0; deg[u]--,deg[v]--; if(deg[v]==1) que.push(v); } } } void tarjan(int u) { int v; low[u]=dfn[u]=++inde; stack[top++]=u; instack[u]=true; for(int i=head[u];i!=-1;i=edge[i].nex) { v=edge[i].v; if(!dfn[v]) { tarjan(v); if(low[u]>low[v]) low[u]=low[v]; } else if(instack[v]&&low[u]>dfn[v]) low[u]=dfn[v]; } if(low[u]==dfn[u]) { block++; do{ v=stack[--top]; instack[v]=false; bblock[block].push_back(v); } while(v!=u); } } void init() { for(int i=0;i<MAXN;i++) { bblock[i].clear(); G[i].clear(); } memset(value,0,sizeof(value)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(deg,0,sizeof(deg)); memset(head,-1,sizeof(head)); memset(instack,0,sizeof(instack)); block=top=inde=tot=0; } int main() { //freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { init(); scanf("%d%d",&p,&m); for(int i=1;i<=p;i++) scanf("%I64d",&value[i]); while(m--) { scanf("%d%d",&u,&v); if(v==u) continue; G[u].push_back(v); G[v].push_back(u); deg[u]++,deg[v]++; } for(int i=1;i<=p;i++) if(deg[i]==1) bfs(i); for(int i=1;i<=p;i++) for(int j=0;j<G[i].size();j++) if(G[i][j]) addedge(i,G[i][j]); for(int i=1;i<=p;i++) if(!dfn[i]) tarjan(i); ll ans=0; for(int i=0;i<=block;i++) if(bblock[i].size()>1&&bblock[i].size()%2) for(int j=0;j<bblock[i].size();j++) ans+=value[bblock[i][j]]; printf("%I64d\n",ans); } return 0; }
E.http://acm.hdu.edu.cn/showproblem.php?pid=5441
思路:离线并查集。把边和询问分别排序。然后往里面加边,设边e的点u,v所在集合的节点数量为cnt[u],cnt[v].那么ans=ans-cnt[u]*(cnt[u]-1)-cnt[v]*(cnt[v]-1)+(cnt[u]+cnt[v])*(cnt[u]+cnt[v]-1), 再把u集合并入v集合,cnt[u]+=cnt[v]。
#include<cstdio> #include<iostream> #include<queue> #include<vector> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int MAXN=25000; const int MAXM=110000; const int MAXQ=6000; int par[MAXN]; int cnt[MAXN]; int ansx[MAXQ]; int n,m,q,T; struct Edge{ int u,v,w; }edge[MAXM]; struct Query{ int w,id; }query[MAXQ]; bool cmp(Edge a,Edge b) { return a.w<b.w; } bool cmp2(Query a,Query b) { return a.w<b.w; } int find(int x) { return x==par[x]?x:par[x]=find(par[x]); } void init() { for(int i=0;i<MAXN;i++) cnt[i]=1,par[i]=i; } int main() { //freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { init(); scanf("%d%d%d",&n,&m,&q); for(int i=0;i<m;i++){ //if(u==v) continue; scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); } sort(edge,edge+m,cmp); for(int i=0;i<q;i++) { scanf("%d",&query[i].w); query[i].id=i; } sort(query,query+q,cmp2); int sh=0; int ans=0; for(int i=0;i<m;i++) { Edge e=edge[i]; //printf("%d %d %d\n",e.w,sh+,query[sh]); while(sh<q&&e.w>query[sh].w) ansx[query[sh++].id]=ans; int u=find(e.u); int v=find(e.v); if(u==v) continue; ans-=cnt[u]*(cnt[u]-1); ans-=cnt[v]*(cnt[v]-1); par[v]=u; cnt[u]+=cnt[v]; ans+=cnt[u]*(cnt[u]-1); } while(sh<q) ansx[query[sh++].id]=ans; for(int i=0;i<q;i++) printf("%d\n",ansx[i]); } return 0; }
G.http://acm.hdu.edu.cn/showproblem.php?pid=5443
签到题,暴力也能过。
H.http://acm.hdu.edu.cn/showproblem.php?pid=5444
思路:模拟建树就好。
#include<cstdio> #include<iostream> #include<queue> #include<vector> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int MAXN=1100; struct Node{ int l,r; int id; }node[MAXN]; void find(int pos,int to) { int x=0; while(1) { if(node[x].id>=to) { if(!node[x].r) { node[x].r=pos; break; } else x=node[x].r; } else { if(!node[x].l) { node[x].l=pos; break; } else x=node[x].l; } } } void solve(int to) { int x=0; while(1) { if(node[x].id==to) break; if(node[x].id>to) { printf("E"); x=node[x].r; } else { printf("W"); x=node[x].l; } } } int T,n,q,to; int main() { //freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { memset(node,0,sizeof(node)); scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&node[i].id); if(i==0) continue; find(i,node[i].id); } scanf("%d",&q); for(int i=0;i<q;i++) { scanf("%d",&to); solve(to); puts(""); } } return 0; }
时间: 2024-10-14 05:14:01