zoukankan      html  css  js  c++  java
  • AcWing 2425. 奇怪的计算器

    分块做法

    Solution

    显然答案关于 X 是单调的,将所有询问按 X 排序。
    那么每次操作需要找出一个分界点 bound , 把询问序列分为溢出和不溢出的两段。

    • 对于不溢出的段,正常维护 tag : +-*
    • 对于溢出的段,区间染色。

    实现的具体 tag 是另 $$ get(i)=b[x] imes mtag[F[x]]+atag[F[x]]+ktag[F[x]] imes a[x] $$
    其中 (b[i]) 是维护的序列, (a[i]) 是原序列, (get(i)) 为当前的真实值。

    Code

    #include<set>
    #include<map>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<bitset>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    const int N=1e5+5,SQ=1000;
    
    int n,m;
    LL Lb,Rb;
    
    struct Require
    {
    	int opt;
    	LL x;
    }a[N];
    
    struct Query
    {
    	int id;
    	LL x;
    	bool operator<(const Query &t) const
    	{
    		return x<t.x;
    	}
    }q[N];
    
    struct Block 
    {
    	int L[SQ],R[SQ];
    	int F[N];
    	
    	LL mtag[SQ],atag[SQ],ktag[SQ]; // get(x) = x*mtag[] + atag[] + ktag[]*a[] 
    	int siz,k;
    	LL a[N],b[N];
    	
    	void Build()
    	{
    		siz=sqrt(n);
    		k=n/siz+(n%siz>0);
    		int i,j;
    		for(i=1;i<=k;i++) {
    			L[i]=R[i-1]+1;
    			R[i]=i*siz;
    		}
    		R[k]=n;
    		for(i=1;i<=k;i++) 
    			for(j=L[i];j<=R[i];j++)
    				F[j]=i;
    		
    		for(i=1;i<=n;i++) a[i]=q[i].x;
    		memcpy(b,a,sizeof b);
    		for(i=1;i<=k;i++) mtag[i]=1,atag[i]=ktag[i]=0;
    	}
    	
    	void pushdown(int x)
    	{
    		if(mtag[x]==1&&atag[x]==0&&ktag[x]==0) return;
    		for(int i=L[x];i<=R[x];i++) 
    			b[i]=b[i]*mtag[x]+atag[x]+ktag[x]*a[i];
    		mtag[x]=1,atag[x]=ktag[x]=0;
    	}
    	
    	inline LL get(int x) { return b[x]*mtag[F[x]]+atag[F[x]]+ktag[F[x]]*a[x]; }
    	
    	void Paint(int x,int y,LL key)
    	{
    		if(y<x) return;
    		int i;
    		if(F[x]==F[y]) {
    			pushdown(F[x]);
    			for(i=x;i<=y;i++) b[i]=key;
    			return;	
    		}
    		pushdown(F[x]);
    		for(i=x;i<=R[F[x]];i++) b[i]=key;
    		for(i=F[x]+1;i<=F[y]-1;i++) mtag[i]=0,atag[i]=key,ktag[i]=0;
    		pushdown(F[y]);
    		for(i=L[F[y]];i<=y;i++) b[i]=key;
    	}
    	
    	void Add(LL key)
    	{
    		int i;
    		for(i=1;i<=k;i++) {
    			if(get(R[i])+key<=Rb) atag[i]+=key;
    			else break;
    		}
    		if(i>k) return;
    		pushdown(i);
    		for(i=L[i];b[i]+key<=Rb;i++) b[i]+=key;
    		Paint(i,n,Rb);
    	}
    	
    	void Sub(LL key)
    	{
    		int i;
    		for(i=1;i<=k && get(R[i])-key<=Lb;i++);//  printf("Query %lld
    ",get(R[i]));
    		if(i==k+1) {
    			Paint(1,n,Lb);
    			return;	
    		}
    		pushdown(i);
    		for(i=L[i];b[i]-key<=Lb;i++);
    		Paint(1,i-1,Lb);
    		int x=F[i];
    		for(;i<=R[x];i++) b[i]-=key;
    		for(i=F[i];i<=k;i++) atag[i]-=key;
    	}
    	
    	void Mul(LL key) 
    	{
    		int i;
    		for(i=1;i<=k;i++) {
    			if(get(R[i])*key<=Rb) 
    				mtag[i]*=key,atag[i]*=key,ktag[i]*=key;
    			else break;
    		}
    		if(i>k) return;
    		pushdown(i);
    		for(i=L[i];b[i]*key<=Rb;i++) b[i]*=key;
    		Paint(i,n,Rb);
    	}
    	
    	void Modify(int key)
    	{
    		int i;
    		for(i=1;i<=k;i++) {
    			if(get(R[i])+a[R[i]]*key<=Rb) ktag[i]+=key;
    			else break;
    		}	
    		if(i>k) return;
    		pushdown(i);
    		for(i=L[i];b[i]+a[i]*key<=Rb;i++) b[i]+=a[i]*key;
    		Paint(i,n,Rb);
    	}
    	
    	void Recover() { for(int i=1;i<=k;i++) pushdown(i); }
    	void print() 
    	{
    		Recover();
    		for(int i=1;i<=n;i++) printf("%lld ",b[i]);
    		printf("
    ");
    	}
    }B;
    
    LL ans[N];
    
    int main()
    {
    //	freopen("1.in","r",stdin);
    	
    	int i;
    	char opt[2];
    	scanf("%d%lld%lld",&m,&Lb,&Rb);
    	for(i=1;i<=m;i++) {
    		scanf("%s%lld",opt,&a[i].x);
    		if(*opt=='+') a[i].opt=1;
    		else if(*opt=='-') a[i].opt=2;
    		else if(*opt=='*') a[i].opt=3;
    		else a[i].opt=4;
    	}	
    	
    	scanf("%d",&n);
    	for(i=1;i<=n;i++) {
    		scanf("%lld",&q[i].x);
    		q[i].id=i;
    	}
    	sort(q+1,q+n+1);
    	B.Build();
    	for(i=1;i<=m;i++) {
    		if(a[i].opt==1) B.Add(a[i].x);
    		else if(a[i].opt==2) B.Sub(a[i].x);
    		else if(a[i].opt==3) B.Mul(a[i].x);
    		else B.Modify(a[i].x);
    		
    //		B.print();
    	}
    	B.Recover();
    	for(i=1;i<=n;i++) 
    		ans[q[i].id]=B.b[i];
    	for(i=1;i<=n;i++) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    训练20191009 2018-2019 ACM-ICPC, Asia East Continent Finals
    [学习笔记] 有上下界网络流
    [HDU4609] 3-idiots
    [HDU1402] A * B Problem Plus
    [HNOI2017] 礼物
    训练20191007 2017-2018 ACM-ICPC Latin American Regional Programming Contest
    [ZJOI2014] 力
    训练20191005 2017-2018 ACM-ICPC Asia East Continent League Final
    [一本通学习笔记] 树链剖分
    [一本通学习笔记] 快速幂
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14054174.html
Copyright © 2011-2022 走看看