zoukankan      html  css  js  c++  java
  • Tishreen-CPC 2018 G. Colors Overflow(分块)

    Problem G. Colors Overflow Input file: standard input Output file: standard output Balloon Color: Dark Green If there is one thing Ziad is good at, it’s creating new colors. In order to use his magical skill to its limit, he decided to start a new career in painting. In order to do so he asked Joud to help him. Joud presented Ziad with an infinite length line. Initially all points of the line are colorless. After examining the line, Ziad noticed that it’s not an ordinary line. Even if a point is painted multiple times, it keeps all the colors without mixing them, and when looking at it you can clearly see all the colors separated. In order to test Ziad’s skills Joud presented him also with Q queries. Each query is of the type "t L R". Queries can be of the following two types, depending on the value of t: 1. "1 L R"This is a task for Ziad to color each sub-segment of the range [L, R] inclusive, each with a unique color that has never been used before. For example when asked to paint the range [3, 6] he will paint segments [3 3], [3 4], [3 5], [3 6], [4 4], [4 5], [4 6], [5, 5], [5 6] and [6 6], each of them with a unique color that has never been used before. 2. "2 L R"This query means Ziad has to look at the range [L, R] inclusive, and write down the number of different colors that appear inside the range. Anyways, Ziad is a little busy packing sugar and tea for his trip to be a judge, so he asked for your help answering these queries.

    Input
    The first line contains a single integer T, denoting the number of test cases.
    Each test case start with a line containing an integer Q (1 ≤ Q ≤ 105), denoting the number of queries.
    The next line contains Q lines describe the queries. Each line has one query of the form "t L R"(1 ≤ t ≤ 2)
    (1 ≤ L ≤ R ≤ 105).
    Output
    For each test case and for each query of the second type, print a single line, indicating the number of
    unique colors in the range [L, R].

    思路:
    将每种颜色看成一条线段,则每次1操作相当于在区间内画了若干条线段,2操作相当于询问指定区间内线段数。
    则对于每次询问,统计[1,L)的右端点数和[1-R]的左端点数,后者减前者,即得到答案(具体可画图理解),而每次1操作增加的左端点数为递减等差数列,增加的右操作数为与之倒序的递增等差数列。
    参考了HH学长的实现思路,利用这个性质,用分块的思想来维护区间内左右端点数。
    在实现上,对于全部询问Q,第一次,我们只更新右端点数,并在询问操作时把指定区间的右端点数减入到对应ans里;第二次,我们只更新左端点数,并在询问操作时把指定区间内左端点数加入到对应ans里。其中第一次完成后,将整个区间左右旋转,并初始化,使得不同但对称的操作,代码能够复用,很巧妙~~具体实现见代码

    #include<iostream>
    #include<algorithm>
    #define de(x) cout<< #x <<" = "<<x<<endl
    using namespace std;
    typedef long long ll;
    const int bsz=350,N=1e5+7,n=1e5+2;
    int bn,bl[N],br[N],sz[N];
    int qop[N],ql[N],qr[N];
    ll ans[N],bs[N],bb[N],bd[N],a[N];
    void init(int n)
    {
    	bn=(n-1)/bsz+1;
    	for (int i=0;i<bn;++i)
    	{
    		bl[i]=i*bsz;
    		br[i]=min(n,(i+1)*bsz);
    		sz[i]=br[i]-bl[i];
    		bs[i]=bd[i]=bb[i]=0;
    	}
    	for (int i=0;i<n;++i)
    		a[i]=0;
    }
    void build(int b) 
    {
    	for (int i=bl[b];i<br[b];++i)
    		a[i]+=bb[b]+(i-bl[b]+1)*bd[b];
    	bb[b]=bd[b]=0;
    }
    void update(int b,int l,int r)
    {
    	int nl=max(l,bl[b]),nr=min(br[b],r);
    	if (nl>=nr)
    		return;
    	if (nr-nl==sz[b])
    	{
    		bb[b]+=nl-l; //维护这一块的基数
    		bd[b]++; //维护这一块的公差
    		bs[b]+=(1+sz[b])*sz[b]/2+(nl-l)*sz[b]; //用求和公式维护这一块端点数
    		return;
    	}
    	for (int i=nl;i<nr;++i) //如果该块没有被包含,则直接暴力维护
    	{
    		bs[b]+=i-l+1; 
    		a[i]+=i-l+1;
    	}
    	return;
    }
    ll query(int b,int l,int r)
    {
    	int nl=max(l,bl[b]),nr=min(br[b],r);
    	if (nl>=nr)
    		return 0;
    	if (nr-nl==sz[b]) //被包含直接返回这一块的值
    		return bs[b];
        //没有被包含时
    	ll res=0; 
    	build(b);//通过之前维护的公差和基数暴力统计端点数
    	for (int i=nl;i<nr;++i)
    		res+=a[i];
    	return res;
    }
    int main()
    {
    	std::ios::sync_with_stdio(0);
    	cin.tie(0);
    	int T;
    	cin>>T;
    	while (T--)
    	{
    		int q;
    		cin>>q;
    		fill_n(ans,q,0);
    		for (int i=0;i<q;++i)
    		{
    			cin>>qop[i]>>ql[i]>>qr[i];
    			--ql[i];
    			--qr[i];
    		}
    		init(n);
    		for (int i=0;i<q;++i)
    		{
    			if (qop[i]==1)
    				for (int j=0;j<bn;++j)
    					update(j,ql[i],qr[i]+1);
    			else 
    				for (int j=0;j<bn;++j)
    					ans[i]-=query(j,0,ql[i]);
                     //旋转
    			ql[i]=n-1-ql[i];
    			qr[i]=n-1-qr[i];
    			swap(ql[i],qr[i]);
    		}
    		init(n);
    		for (int i=0;i<q;++i)
    		{
    			if (qop[i]==1)
    				for (int j=0;j<bn;++j)
    					update(j,ql[i],qr[i]+1);
    			else
    			{
    				for (int j=0;j<bn;++j)
    					ans[i]+=query(j,ql[i],n);
    				cout<<ans[i]<<endl;
    			}
    		}		
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux 查询文件在多个目录里面,只保留一个
    mysql 定时备份
    mysql 赋予权限报错Column count of mysql.user is wrong. Expected 45, found 43. The table is probably corrupted
    Mysql 启动报错Error: page 5 log sequence number 2580579963
    docker 限制日志文件大小和数量
    docker 安装
    MVC3学习第十五章 武林外传大结局
    MVC3学习第十四章 佟掌柜第三弹——MVC3下利用陕北吴旗娃的验证码控件实现验证码功能以及在mvc3下使用编辑器
    MVC3学习第十三章 佟掌柜第二弹——MVC3下利用陕北吴旗娃的分页控件实现数据分页
    MVC3学习第十二章 佟掌柜第一弹----利用MVC3实现用户的注册登录和了解MVC中的分部视图、用户控件
  • 原文地址:https://www.cnblogs.com/orangee/p/9215303.html
Copyright © 2011-2022 走看看