欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Transformation HDU - 4578

程序员文章站 2022-06-08 14:09:15
...

点击打开链接

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

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

Transformation HDU - 4578

而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;
}

 

相关标签: 线段树 HDU