Transformation HDU - 4578

点击打开链接

维护一次幂二次幂三次幂的三个区间和 再维护乘法加法赋值的三个lazy标记

几个幂次和之间是有公式的 如图


而lazy标记的使用也需要技巧

首先赋值的优先级最高 只要赋值操作 其他两种操作直接舍弃 而加法和乘法虽然优先级一样 但是乘法操作不止影响乘法lazy 也影响加法lazy 具体见代码


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define M 10007

struct node
{
	int l;
	int r;
	ll val1;
	ll val2;
	ll val3;
	ll laz1;
	ll laz2;
	ll laz3;
};

node tree[400010];
int n;

void changeI(int cur,ll val)
{
	ll len;
	len=tree[cur].r-tree[cur].l+1;
	tree[cur].val3=(tree[cur].val3+3*val*tree[cur].val2+3*val*val*tree[cur].val1+val*val*val*len)%M;
	tree[cur].val2=(tree[cur].val2+2*val*tree[cur].val1+val*val*len)%M;
	tree[cur].val1=(tree[cur].val1+val*len)%M;
	return;
}

void changeII(int cur,ll val)
{
	tree[cur].val1=(tree[cur].val1*val)%M;
	tree[cur].val2=(tree[cur].val2*val*val)%M;
	tree[cur].val3=(tree[cur].val3*val*val*val)%M;
	return;
}

void changeIII(int cur,ll val)
{
	ll len;
	len=tree[cur].r-tree[cur].l+1;
	tree[cur].val1=(val*len)%M;
	tree[cur].val2=(((val*val)%M)*len)%M;
	tree[cur].val3=(((val*val)%M)*((val*len)%M))%M;
	return;
}

void pushup(int cur)
{
	tree[cur].val1=(tree[2*cur].val1+tree[2*cur+1].val1)%M;
	tree[cur].val2=(tree[2*cur].val2+tree[2*cur+1].val2)%M;
	tree[cur].val3=(tree[2*cur].val3+tree[2*cur+1].val3)%M;
	return;
}

void pushdown(int cur)
{
    if(tree[cur].laz3!=-1)
    {
        changeIII(2*cur,tree[cur].laz3);
        tree[2*cur].laz3=tree[cur].laz3;
        changeIII(2*cur+1,tree[cur].laz3);
        tree[2*cur+1].laz3=tree[cur].laz3;
        tree[2*cur].laz1=0,tree[2*cur+1].laz1=0;
        tree[2*cur].laz2=1,tree[2*cur+1].laz2=1;
        tree[cur].laz3=-1;
    }
    if(tree[cur].laz1!=0||tree[cur].laz2!=1)
    {
        //tree[2*cur].laz1=(tree[2*cur].laz1*tree[cur].laz2+tree[cur].laz1)%M;
        changeII(2*cur,tree[cur].laz2);
        changeI(2*cur,tree[cur].laz1);
        tree[2*cur].laz2=(tree[2*cur].laz2*tree[cur].laz2)%M;
        tree[2*cur].laz1=(tree[2*cur].laz1*tree[cur].laz2+tree[cur].laz1)%M;
        changeII(2*cur+1,tree[cur].laz2);
        changeI(2*cur+1,tree[cur].laz1);
        tree[2*cur+1].laz2=(tree[2*cur+1].laz2*tree[cur].laz2)%M;
        tree[2*cur+1].laz1=(tree[2*cur+1].laz1*tree[cur].laz2+tree[cur].laz1)%M;
        tree[cur].laz1=0;
        tree[cur].laz2=1;
    }
	return;
}

void build(int l,int r,int cur)
{
	int m;
	tree[cur].l=l;
	tree[cur].r=r;
	tree[cur].val1=0;
	tree[cur].val2=0;
	tree[cur].val3=0;
	tree[cur].laz1=0;
	tree[cur].laz2=1;
	tree[cur].laz3=-1;
	if(l==r) return;
	m=(l+r)/2;
	build(l,m,2*cur);
	build(m+1,r,2*cur+1);
	return;
}

void update(int op,int pl,int pr,ll val,int cur)
{
	if(pl<=tree[cur].l&&tree[cur].r<=pr)
	{
		if(op==1)
		{
			changeI(cur,val);
			tree[cur].laz1=(tree[cur].laz1+val)%M;
		}
		else if(op==2)
		{
			changeII(cur,val);
			tree[cur].laz2=(tree[cur].laz2*val)%M;
			tree[cur].laz1=(tree[cur].laz1*val)%M;
		}
		else
		{
			changeIII(cur,val);
			tree[cur].laz1=0,tree[cur].laz2=1,tree[cur].laz3=val;
		}
		return;
	}
	pushdown(cur);
	if(pl<=tree[2*cur].r) update(op,pl,pr,val,2*cur);
	if(pr>=tree[2*cur+1].l) update(op,pl,pr,val,2*cur+1);
	pushup(cur);
	return;
}

ll query(int tp,int pl,int pr,int cur)
{
	ll res;
	if(pl<=tree[cur].l&&tree[cur].r<=pr)
	{
		if(tp==1) return tree[cur].val1;
		else if(tp==2) return tree[cur].val2;
		else return tree[cur].val3;
	}
	pushdown(cur);
	res=0;
	if(pl<=tree[2*cur].r) res=(res+query(tp,pl,pr,2*cur))%M;
	if(pr>=tree[2*cur+1].l) res=(res+query(tp,pl,pr,2*cur+1))%M;
	return res;
}

int main()
{
	ll val;
	int q,op,l,r;
	while(1)
	{
	    scanf("%d%d",&n,&q);
		if(n==0&&q==0) break;
		build(1,n,1);
		while(q--)
		{
			scanf("%d%d%d%lld",&op,&l,&r,&val);
			if(op!=4) update(op,l,r,val,1);
			else printf("%lld\n",query(val,l,r,1)%M);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/80397920
今日推荐