zoukankan      html  css  js  c++  java
  • 历史

    2019.8.23

    3.1 题目描述

    历史学家小A正在研究一个奇怪的王国的历史。当前阶段的任务是研究该国的交通。根据这个奇怪的王国的史书记载,史书开始记载前这个王国有 n 个城市(城市从 0 开
    始标号),但所有城市之间都没有道路相连。

    每一年,在位的国王会修建一条 x 到 y 的双向道路,一条道路可能被修建多次,但不会修建起点和终点为同一个城市的道路。

    而在这之间,国王会计划进行若干次旅行。对于计划进行的一次旅行 st->ed,如果当时能完成这次旅行,而 t 年前不能完成这次旅行,那么国王会对之前的建设成果感到满意, 否则他会很生气,并在下一次计划旅行前都让史官记录下错误的修建道路的信息,即把 x、y 记作(x+n-c) mod n,(y+n-c) mod n。

    当然在这些年中也发生了若干次国王的交替,初始国王的 c 值为 0,而每个国王的 c 值不一定相同,但在国王在位期间 c 值不会改变,新上位的国王开始处于不生气的状态。
    请根据史书帮助小 A 得出国王每次对于计划旅行是否满意,从而辅助小 A 能够研究该国的交通信息。

    3.2 输入格式

    第一行为两个整数 n,m,表示初始城市数和历史书记载的内容数。接下来 m 行,每行是以下三种格式之一:

    1. K v :表示国王交替,新国王的 c 值为 v

    2. R x y:表示史书上记载的是国王修建了 x 到 y 的双向道路,但注意这个记录的可能不是实际状况。

    3. T st ed t:表示国王计划进行的一次 st->ed 的旅行,且比较的是 t 年前的情况(国王可能会和史书开始记载以前的情况比较),注意这个记录的肯定是实际情况。

    注意只有遇到 R 操作才会使年份的计数+1。

    3.3 输出格式

    输对于每个 T 的记录输出一行,如果此次计划旅行令国王满意,则输出 Y,否则输出 X。

    3.4 样例输入

    3 7
    R 0 1
    T 0 1 1
    K 1
    R 0 1
    T 0 1 1
    R 0 1
    T 0 2 1
    

    3.5 样例输出

    Y N Y
    

    3 .6 数据范围与约定

    对于 30%的数据,保证 n<=1000 ,m<=3000。另 30%的数据满足没有发生国王的交替。

    对于 100%的数据,保证 n,m<=300000,0<=v,x,y,st,ed<n,0<=t<m。数据有梯度


    题目所求的是两个点的连通性,可以用并查集很好地维护。

    要求询问历史版本,可持久化并查集?其实没这个必要,考虑到只是求历史版本的值,而不是真正地变成历史状态,所以可以预先在之前访问历史版本的时候就把现在的问题求解出来,在当前查询的时候就可以直接调用了,因为要预处理所以考虑离线。(细节有点多)

    Code:

    #include<stdio.h>
    #define N 300007
    
    char op[N];
    int a[N],b[N],c[N],n,m,head[N],cnt=1,sta[N],t,fa[N];
    bool flag[N],tag;
    
    inline int find(int x){
    	if(fa[x]==x) return x;
    	return fa[x]=find(fa[x]);
    }
    struct E{
    	int next,to;
    }e[N<<1];
    
    template<class T>
    inline void read(T &x){
    	x=0;int flag=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    	x*=flag;
    }
    inline int max(int x,int y){return x>y? x:y;}
    inline void read_char(char &x){
    	x=getchar();
    	while(x<'A'||x>'Z') x=getchar();
    }
    inline void add(int id,int to){
    	e[++cnt]=(E){head[id],to};
    	head[id]=cnt;
    }
    inline void dfs(int u){
    	if(u>m) return ;
    	if(op[u]=='K') tag=0;
    	if(op[u]=='R'){
    		int x=a[u],y=b[u];
    		if(tag){
    			x=((x-1)%n+n+c[u])%n+1;
    			y=((y-1)%n+n+c[u])%n+1;
    		}
    		int fa_x=find(x),fa_y=find(y);
    		fa[fa_y]=fa_x;
    	}
    	if(op[u]=='T') flag[u]^=(find(a[u])==find(b[u])),tag=flag[u]^1;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		flag[v]=(find(a[v])==find(b[v]));
    	}
    	dfs(u+1);
    }
    int main(){
    	freopen("history.in","r",stdin);
    	freopen("history.out","w",stdout);
    	read(n);read(m);
    	for(int i=1;i<=n;i++) fa[i]=i;
    	int qwq;
    	for(int i=1;i<=m;i++){
    		read_char(op[i]);
    		if(op[i]=='K') read(c[i]);
    		else c[i]=c[i-1];
    		if(op[i]=='R') read(a[i]),read(b[i]),sta[++t]=i;
    		else if(op[i]=='T') read(a[i]),read(b[i]),read(qwq),add(sta[max(0,t-qwq)],i);
    		a[i]++,b[i]++;
    	}
    	dfs(0);
    	for(int i=1;i<=m;i++)
    		if(op[i]=='T') printf("%c\n",flag[i]? 'Y':'N');
    }
    
  • 相关阅读:
    正定矩阵与半正定矩阵定义与判别
    LQR (线性二次型调节器)的直观推导及简单应用
    simulink模块使用方式
    无人驾驶领域现有的主流智能车辆仿真软件具体情况介绍
    什么是在环测试
    C# Dictionary 是否包含key
    jquery.显示隐藏切换
    easyui-dialog
    Visual Studio 命令行wsdl生成C#操作类
    使用C#创建Windows服务
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/11400335.html
Copyright © 2011-2022 走看看