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;
    }
    
    
  • 相关阅读:
    网络编程
    网络参考模型
    面向对象中类的成员
    Forward(请求转发)和Redirect(重定向)的比较
    AOP详解
    JDK动态代理和CGLib代理对比
    内存可见性问题分析
    Java中创建对象的5种方式
    基于Spring的动态路由AbstractRoutingDataSource实现动态分库
    在java中String类为什么要设计成final?
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10164579.html
Copyright © 2011-2022 走看看