zoukankan      html  css  js  c++  java
  • CF911G Mass Change Queries(线段树+暴力)

    cf机子真的快。

    其实这个题的维护的信息还是很巧妙的。

    首先,观察到题目中涉及到,区间修改这个操作,然后最后只查询一次,我们不妨用线段树来维护这个过程。

    但是貌似直接维护每个位置的值可能不太好维护。
    这时候我们考虑

    每一个节点维护一个(to)数组,其中(to[i])表示这个节点对应的区间里面,(i)这个值将会变成哪个值。

    一开始,每个节点的(to[i]=i)

    由于最后是单点询问,所以不用(up)操作。

    现在考虑(pushdown)应该怎么写。
    对于当前节点的(to[i])应该等于他的父亲的(to[to[i]]),就是他原本的i指向的点,在父亲里会指向哪里。

    void pushdown(int root,int l,int r)
    {
    	for (rint i=1;i<=100;++i) 
    	{
    		f[root<<1].to[i]=f[root].to[f[root<<1].to[i]];
    		f[root<<1|1].to[i]=f[root].to[f[root<<1|1].to[i]];
    	}
    	for (rint i=1;i<=100;++i)
    	  f[root].to[i]=i;
    }
    

    然后(update)的时候,直接暴力扫一遍即可。
    将所有(to[i]=x)的to,都修改成(y).

    询问的时候,直接询问(to)就可以,直接给代码了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define mk make_pair
    #define ll long long
    #define rint register int
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 2e5+1e2;
    
    int n;
    int val[maxn];
    
    struct Node{
    	int to[102];
    };
    
    Node f[4*maxn];
    
    void pushdown(int root,int l,int r)
    {
    	for (rint i=1;i<=100;++i) 
    	{
    		f[root<<1].to[i]=f[root].to[f[root<<1].to[i]];
    		f[root<<1|1].to[i]=f[root].to[f[root<<1|1].to[i]];
    	}
    	for (rint i=1;i<=100;++i)
    	  f[root].to[i]=i;
    }
    
    void build(int root,int l,int r)
    {
        for (rint i=1;i<=100;++i) f[root].to[i]=i;
    	if (l==r)
    	{
    		return;
    	}
    	int mid = l+r >>1;
    	build(root<<1,l,mid);
    	build(root<<1|1,mid+1,r);
    }
    
    void update(int root,int l,int r,int x,int y,int p,int pp)
    {
    	if (x<=l && r<=y)
    	{
    		for (int i=1;i<=100;i++)
    		{
    			if (f[root].to[i]==p) f[root].to[i]=pp;
    		}
    		return;
    	}
    	pushdown(root,l,r);
    	int mid = l+r >>1;
    	if (x<=mid) update(root<<1,l,mid,x,y,p,pp);
    	if (y>mid) update(root<<1|1,mid+1,r,x,y,p,pp);
    }
    
    int query(int root,int l,int r,int x,int p)
    {
    	if (l==r)
    	{
    		return f[root].to[p];
    	}
    	pushdown(root,l,r);
    	int mid = l+r >> 1;
    	if (x<=mid) return query(root<<1,l,mid,x,p);
    	if (x>mid) return query(root<<1|1,mid+1,r,x,p);
    }
    
    int main()
    {
      n=read();
      for (rint i=1;i<=n;++i) val[i]=read();
      build(1,1,n);
     // for (rint i=1;i<=n;++i)
      //{
      //	 cout<<query(1,1,n,i,val[i])<<" ";
      //}
    //  cout<<endl;
      int q=read();
      for (rint i=1;i<=q;++i)
      {
      	 int l=read(),r=read(),x=read(),y=read();
      	 update(1,1,n,l,r,x,y);
      	// cout<<i<<":"<<endl;
      // for (rint i=1;i<=n;++i)
     // {
      //	 cout<<query(1,1,n,i,val[i])<<" ";
      //}
     // cout<<endl;
      }
      for (rint i=1;i<=n;++i)
      {
      	 cout<<query(1,1,n,i,val[i])<<" ";
      }
      return 0;
    }
    
    
  • 相关阅读:
    未能加载文件或程序集“System.EnterpriseServices, Version=4.0.0.0或2.0.0.0
    解决本地调用office组件成功,但是发布到IIS中出现的错误(检索COM类工厂中CLSID为{00024500-0000-0000-C000-000000000046}的组件时失败)
    未能找到类型或命名空间名称“Coco”(是否缺少 using 指令或程序集引用)
    SQL截取字段字符串的方法
    C# 128位AES 加密解密 (转)
    检索 COM 类工厂中 CLSID 为 {13C28AD0-F195-4319-B7D7-A1BDAA329FB8} 的组件时失败,原因是出现以下错误: 80040154
    js 获取时间比较全,留备用(zhuan)
    windows之如何把iso文件转换为VHD文件
    python之三行代码发送邮件
    RobotFramework第二篇之web自动化
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10164579.html
Copyright © 2011-2022 走看看