• [NOI2018]归程


    题目

    思路

    做过peaks的话这道题简直就水的不行((peaks)弱化版?)

    先从1向所有点跑一次最短路求出(dis)(此题略卡(spfa)),按照海拔从大到小做出(kruskal)重构树,(dfs)一遍预处理出每个点对应的子树的最小(dis),对于每个海拔限制,倍增找到深度最小的满足条件的节点,则(ans=mindis)

    两道题的不同点:peaks还要求第k小,要用主席树;这道题求最小值,可以直接预处理(当然还要跑最短路)

    Code

    (受(peaks)影响,蠢的一批的用(ST+dfs)序求的子树中的最小(dis),这个东西显然可以(O(1))递推的。。。懒得改了)

    #include<bits/stdc++.h>
    #define N 400005
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)<(y)?(x):(y))
    using namespace std;
    int T,n,m,ndsum,fa[N],val[N];
    int dis[N],l[N],r[N],rev[N],cc;
    int f[N][20],dep[N],st[N][20],lg[N];
    bool vis[N];
    
    struct Edge
    {
    	int next,to,dis;
    }edge[N<<2];int head[N],cnt=1;
    struct E {int u,v,l,a;} e[N];
    
    void add_edge(int from,int to,int dis)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].dis=dis;
    	head[from]=cnt;
    }
    template <class T>
    void read(T &x)
    {
    	char c;int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
    }
    
    void init()
    {
    	memset(dep,0,sizeof(dep));
    	memset(head,0,sizeof(head));
    	cnt=1;cc=0;
    }
    
    bool cmp(E a,E b) {return a.a>b.a;}
    int find(int x) {return x==fa[x] ? x : fa[x]=find(fa[x]);}
    void dijkstra(int s)
    {
    	memset(dis,100,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	priority_queue< pair<int,int> > q;
    	dis[s]=0; q.push(make_pair(-dis[s],s));
    	while(!q.empty())
    	{
    		int u=q.top().second; q.pop();
    		if(vis[u]) continue;
    		vis[u]=1;
    		for(int i=head[u];i;i=edge[i].next)
    		{
    			int v=edge[i].to;
    			if(dis[v]>dis[u]+edge[i].dis)
    			{
    				dis[v]=dis[u]+edge[i].dis;
    				if(!vis[v]) q.push(make_pair(-dis[v],v));
    			}
    		}
    	}
    }
    void kruskal()
    {
    	ndsum=n;
    	for(int i=1;i<=n*2;++i) fa[i]=i;
    	sort(e+1,e+m+1,cmp);
    	int tot=0;
    	for(int i=1;i<=m;++i)
    	{
    		int fx=find(e[i].u),fy=find(e[i].v);
    		if(fx==fy) continue;
    		val[++ndsum]=e[i].a;
    		add_edge(ndsum,fx,0);
    		add_edge(ndsum,fy,0);
    		fa[fx]=fa[fy]=ndsum;
    	}
    }
    void dfs(int rt)
    {
    	l[rt]=n+1,r[rt]=0;
    	if(rt<=n)
    	{
    		l[rt]=r[rt]=++cc;
    		rev[cc]=rt;
    		return;
    	}
    	for(int i=head[rt];i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		dep[v]=dep[rt]+1;
    		f[v][0]=rt;
    		for(int j=1;j<20;++j) f[v][j]=f[f[v][j-1]][j-1];
    		dfs(v);
    		l[rt]=Min(l[rt],l[v]);
    		r[rt]=Max(r[rt],r[v]);
    	}
    }
    int lca(int start,int maxx)
    {
    	for(int i=19;i>=0;--i)
    	  if(f[start][i]&&val[f[start][i]]>maxx)
    		start=f[start][i];
    	return start;
    }
    void ST()
    {
    	memset(st,125,sizeof(st));
    	for(int i=n;i>=1;--i)
    	{
    		st[i][0]=dis[rev[i]];
    		for(int j=1;i+(1<<j)-1<=n;++j)
    		{
    			st[i][j]=Min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
    		}
    	}
    }
    int ask(int l,int r)
    {
    	int tp=lg[r-l+1];
    	return Min(st[l][tp],st[r-(1<<tp)+1][tp]);
    }
    
    int main()
    {
    	read(T);
    	lg[0]=-1;
    	for(int i=1;i<N;++i) lg[i]=lg[i>>1]+1;
    	while(T--)
    	{
    		init();
    		read(n);read(m);
    		for(int i=1;i<=m;++i)
    		{
    			read(e[i].u);read(e[i].v);
    			read(e[i].l);read(e[i].a);
    			add_edge(e[i].u,e[i].v,e[i].l);
    			add_edge(e[i].v,e[i].u,e[i].l);
    		}
    		dijkstra(1);
    		memset(head,0,sizeof(head));
    		cnt=1;
    		kruskal();
    		dfs(ndsum);
    		ST();
    		
    		int q,k,s,lasans=0;
    		read(q);read(k);read(s);
    		while(q--)
    		{
    			int v,p;
    			read(v);read(p);
    			v=((long long)v+k*lasans-1)%n+1;
    			p=((long long)p+k*lasans)%(s+1);
    			int lc=lca(v,p);
    			lasans=ask(l[lc],r[lc]);
    			printf("%d
    ",lasans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    JAVA-初步认识-常用对象API(集合框架-重点方法keyset演示图解)
    JAVA-初步认识-常用对象API(集合框架-常用方法演示)
    JAVA-初步认识-常用对象API(集合框架-Map集合特点常用方法)
    JAVA-初步认识-常用对象API(集合框架-练习-字符串长度排序)
    JAVA-初步认识-常用对象API(集合框架-treeset集合-二叉树)
    JAVA-初步认识-常用对象API(集合框架-treeset集合-Comparator比较器)9
    JAVA-初步认识-常用对象API(集合框架-treeset集合)
    JAVA-初步认识-常用对象API(集合框架-LinkedHashset集合)
    Spring整合hibernate的一个例子:用事务买书
    Spring整合hibernate的一个例子:用事务买书
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11651778.html
Copyright © 2020-2023  润新知