HDU - 4578Transformation——線段樹+區間加法修改+區間乘法修改+區間置數+區間和查詢+區間平方和查詢+區間立方和查詢

【題目描述】
HDU - 4578Transformation
Problem Description
Yuanfang is puzzled with the question below:
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<—ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<—ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<—c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.

Input
There are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: “1 x y c” or “2 x y c” or “3 x y c”. Operation 4 is in this format: “4 x y p”. (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.

Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.

Sample Input

5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0

Sample Output

307
7489
【題目分析】
這道題真的是老妖怪級別的了,此處省略吐槽兩千字
題目的意思很明確,就是給你一個全為0 的數組,讓你實現區間加法修改+區間乘法修改+區間置數+區間和查詢+區間平方和查詢+區間立方和查詢功能。
根據需求,每個區間有三個需要維護的數據——區間和,區間平方和,區間立方和,有三種修改操作,因此需要三種標記,分別用來標記區間加法、區間乘法、區間置數
難點在于對于三種數據的快速維護和標記之間的關系

  1. 標記之間的關系(關鍵)
    我們為了實現區間修改就需要引入lazy標記(沒有掌握這個的同學請出門左拐,詳見線段樹入門) ,但是當存在多種標記的時候處理標記的順序就很重要,因為這反應了修改操作的效用關系以及時間關系。
    上面三種操作里面最厲害的顯然是區間置數,一個區間置數后之前什么加法乘法統統作廢。然后是區間乘法,因為區間乘法,因為對同一個區間,后來的乘法標記會對之前的加法標記產生影響,但是后來的加法標記對乘法標記卻沒有什么影響(先算乘法再算加法嘛)
    因此在處理區間置數的時候可以直接對區間加法置零,對區間乘法的標記置一
    在處理區間乘法的時候如果發現下面的區間還要進行區間加法就要修改區間加法的標記(給標記也乘上同一個數)
    在處理區間加法的時候對其他標記沒有影響
    同樣的,在下傳標記的時候同樣要面對這樣的問題
    這樣,后面的操作對前面操作的影響就能傳遞下去
  2. 三種數據的快速維護
    區間置數后三種數據直接計算
    區間乘法后立方和乘上乘數的立方,平方和乘上乘數的平方,區間和乘上乘數,需要注意取模(時刻取模,時刻提防爆數據)
    最麻煩的是區間加法
    對于區間和,應該加上區間長度乘上加數
    對于平方和,見下圖
    在這里插入圖片描述
    立方和同理
    【AC代碼】(可寫死我了)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<climits>
#include<queue>
#include<vector>using namespace std;
typedef long long ll;const int MAXN=100005;
const ll MOD=10007;struct node
{ll a,aa,aaa;
}tree[MAXN<<2];
ll set[MAXN<<2],add[MAXN<<2],multiply[MAXN<<2];
int n,m;
ll t;void pushdown(int k,int l,int r)
{int mid=(l+r)>>1; if(set[k]>0){tree[k<<1].a=set[k]%MOD*(mid-l+1)%MOD; tree[k<<1|1].a=set[k]%MOD*(r-mid)%MOD;tree[k<<1].aa=set[k]%MOD*set[k]%MOD*(mid-l+1)%MOD; tree[k<<1|1].aa=set[k]%MOD*set[k]%MOD*(r-mid)%MOD;tree[k<<1].aaa=set[k]%MOD*set[k]%MOD*set[k]%MOD*(mid-l+1)%MOD; tree[k<<1|1].aaa=set[k]%MOD*set[k]%MOD*set[k]%MOD*(r-mid)%MOD;set[k<<1]=set[k<<1|1]=set[k];	add[k<<1]=add[k<<1|1]=0;	//直接取消標記multiply[k<<1]=multiply[k<<1|1]=1;	//直接取消標記set[k]=0;}if(multiply[k]!=1){tree[k<<1].a=tree[k<<1].a*multiply[k]%MOD;tree[k<<1|1].a=tree[k<<1|1].a*multiply[k]%MOD;tree[k<<1].aa=tree[k<<1].aa*multiply[k]%MOD*multiply[k]%MOD;tree[k<<1|1].aa=tree[k<<1|1].aa*multiply[k]%MOD*multiply[k]%MOD;tree[k<<1].aaa=tree[k<<1].aaa*multiply[k]%MOD*multiply[k]%MOD*multiply[k]%MOD;tree[k<<1|1].aaa=tree[k<<1|1].aaa*multiply[k]%MOD*multiply[k]%MOD*multiply[k]%MOD;multiply[k<<1]=multiply[k<<1]*multiply[k]%MOD;multiply[k<<1|1]=multiply[k<<1|1]*multiply[k]%MOD;if(add[k<<1]) add[k<<1]=add[k<<1]*multiply[k]%MOD;	//注意對加法標記的影響if(add[k<<1|1]) add[k<<1|1]=add[k<<1|1]*multiply[k]%MOD;-multiply[k]=1;}if(add[k]>0){tree[k<<1].aaa=(((tree[k<<1].aaa+3*add[k]%MOD*tree[k<<1].aa%MOD)%MOD+3*add[k]%MOD*add[k]%MOD*tree[k<<1].a%MOD)%MOD+(mid-l+1)*add[k]%MOD*add[k]%MOD*add[k]%MOD)%MOD; //順序很重要,應該先立方后平方再區間和(因為會用到原始數據)tree[k<<1|1].aaa=(((tree[k<<1|1].aaa+3*add[k]%MOD*tree[k<<1|1].aa%MOD)%MOD+3*add[k]%MOD*add[k]%MOD*tree[k<<1|1].a%MOD)%MOD+(r-mid)*add[k]%MOD*add[k]%MOD*add[k]%MOD)%MOD; tree[k<<1].aa=((tree[k<<1].aa+add[k]*add[k]%MOD*(mid-l+1)%MOD)%MOD+2*add[k]%MOD*tree[k<<1].a%MOD)%MOD;tree[k<<1|1].aa=((tree[k<<1|1].aa+add[k]*add[k]%MOD*(r-mid)%MOD)%MOD+2*add[k]%MOD*tree[k<<1|1].a%MOD)%MOD;tree[k<<1].a=(tree[k<<1].a+add[k]*(mid-l+1)%MOD)%MOD;tree[k<<1|1].a=(tree[k<<1|1].a+add[k]*(r-mid)%MOD)%MOD;add[k<<1]=(add[k<<1]+add[k])%MOD;add[k<<1|1]=(add[k<<1|1]+add[k])%MOD;//時刻注意取模add[k]=0;}
}void update(int k)
{tree[k].a=(tree[k<<1].a+tree[k<<1|1].a)%MOD;tree[k].aa=(tree[k<<1].aa+tree[k<<1|1].aa)%MOD;tree[k].aaa=(tree[k<<1].aaa+tree[k<<1|1].aaa)%MOD;
}void interval_add(int k,int l,int r,int x,int y,ll z)
{if(l>=x && r<=y){tree[k].aaa=(((tree[k].aaa+3*z%MOD*tree[k].aa%MOD)%MOD+3*z%MOD*z%MOD*tree[k].a)%MOD+(r-l+1)*z%MOD*z%MOD*z%MOD)%MOD;tree[k].aa=((tree[k].aa+2*z%MOD*tree[k].a%MOD)%MOD+(r-l+1)*z%MOD*z%MOD)%MOD;tree[k].a=(tree[k].a+z*(r-l+1)%MOD)%MOD;add[k]=(add[k]+z)%MOD;return;}int mid=(l+r)>>1;pushdown(k,l,r);if(x<=mid) interval_add(k<<1,l,mid,x,y,z);if(y>mid) interval_add(k<<1|1,mid+1,r,x,y,z);update(k); 
}void interval_multiply(int k,int l,int r,int x,int y,ll z)
{if(l>=x && r<=y){multiply[k]=(multiply[k]*z)%MOD;if(add[k]>0){add[k]=(add[k]*z)%MOD;}tree[k].a=tree[k].a*z%MOD;tree[k].aa=tree[k].aa*z%MOD*z%MOD;tree[k].aaa=tree[k].aaa*z%MOD*z%MOD*z%MOD;return;}int mid=(l+r)>>1;pushdown(k,l,r);if(x<=mid) interval_multiply(k<<1,l,mid,x,y,z);if(y>mid) interval_multiply(k<<1|1,mid+1,r,x,y,z);update(k); 
}void interval_set(int k,int l,int r,int x,int y,ll z)
{if(l>=x && r<=y){tree[k].a=z*(r-l+1)%MOD;tree[k].aa=z*z%MOD*(r-l+1)%MOD;tree[k].aaa=z*z%MOD*z%MOD*(r-l+1)%MOD;add[k]=0;multiply[k]=1;set[k]=z;return;}int mid=(l+r)>>1;pushdown(k,l,r);if(x<=mid) interval_set(k<<1,l,mid,x,y,z);if(y>mid) interval_set(k<<1|1,mid+1,r,x,y,z);update(k); 
}ll query(int k,int l,int r,int x,int y,int z)
{if(l>=x && r<=y){if(z==1)return tree[k].a%MOD;if(z==2)return tree[k].aa%MOD;if(z==3)return tree[k].aaa%MOD;}int mid=(l+r)>>1;ll ans=0;pushdown(k,l,r);if(x<=mid) ans=(ans+query(k<<1,l,mid,x,y,z))%MOD;if(y>mid) ans=(ans+query(k<<1|1,mid+1,r,x,y,z))%MOD;return ans;
}void search_point(int k,int l,int r,int x)
{if(l==r && l==x){t=tree[k].a;return;}pushdown(k,l,r);int mid=(l+r)>>1;if(x<=mid) search_point(k<<1,l,mid,x);else search_point(k<<1|1,mid+1,r,x);
}void test()
{for(int i=1;i<=n;i++){search_point(1,1,n,i);printf("%lld ",t);}printf("\n");
}int main()
{ll cmd,u,v,w;while(~scanf("%d%d",&n,&m) && (n||m)){memset(tree,0,sizeof(tree));memset(set,0,sizeof(set));memset(add,0,sizeof(add));for(int i=0,j=n<<2;i<=j;i++) multiply[i]=1;for(int i=0;i<m;i++){scanf("%lld%lld%lld%lld",&cmd,&u,&v,&w);if(cmd==1){interval_add(1,1,n,u,v,w%MOD);}else if(cmd==2){interval_multiply(1,1,n,u,v,w%MOD);}else if(cmd==3){interval_set(1,1,n,u,v,w%MOD);}else if(cmd==4){//test();printf("%lld\n",query(1,1,n,u,v,w));}}}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384144.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384144.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384144.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[C++基礎]034_C++模板編程里的主版本模板類、全特化、偏特化(C++ Type Traits)

http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1. 主版本模板類 首先我們來看一段初學者都能看懂&#xff0c;應用了模板的程序&#xff1a; 1 #include <iostream>2 using namespace std;3 4 template<class T1, class T2>5 clas…

自定義類型: 結構體,枚舉,聯合

1.結構體 個人認為結構體和數組特別相似&#xff0c;只不過結構體和數組的區別在于結構體的成員可以是不同類型&#xff0c;而數組成員類型是相同的。 &#xff08;1&#xff09;結構體的聲明 struct tag {成員列表//至少得有一個成員 }值列表;//值列表可以省略 struct {int a…

詳解C++中的函數調用和下標以及成員訪問運算符的重載

http://www.jb51.net/article/78436.htm 這篇文章主要介紹了詳解C中的函數調用和下標以及成員訪問運算符,講到了這些二元運算符使用的語法及重載,需要的朋友可以參考下函數調用 使用括號調用的函數調用運算符是二元運算符。 語法 ?1primary-expression ( expression-list )備…

A計劃——BFS

【題目描述】 可憐的公主在一次次被魔王擄走一次次被騎士們救回來之后&#xff0c;而今&#xff0c;不幸的她再一次面臨生命的考驗。魔王已經發出消息說將在T時刻吃掉公主&#xff0c;因為他聽信謠言說吃公主的肉也能長生不老。年邁的國王正是心急如焚&#xff0c;告招天下勇士…

使用openssl的md5庫

http://blog.csdn.net/sinat_35297665/article/details/78244523 在linux機器上&#xff0c;有一個命令可以計算出文件的md5值&#xff0c;那就是md5sum&#xff0c;如果沒有的話&#xff0c;就需要安裝RPM包&#xff1a;coreutils。 現在我們使用openssl的庫也可以方便的計算出…

主席樹入門

今天學習了一下主席樹&#xff08;名字這么強的嘛&#xff09; 雖然直接理解起來不容易&#xff0c;但是這種解決問題的思想其實并不陌生。 我們可以首先來看維護整個區間第K大的線段樹 我們將[l,r]區間內數字的多少用線段樹進行維護&#xff0c;這樣的話為了求取區間第k大&…

Socket網絡編程--小小網盤程序(1)

http://www.cnblogs.com/wunaozai/p/3886588.html 這個系列是準備講基于Linux Socket進行文件傳輸。簡單的文件傳輸就是客戶端可以上傳文件&#xff0c;可以從服務器端下載文件。就這么兩個功能如果再加上身份驗證&#xff0c;就成了FTP服務器了&#xff0c;如果對用戶的操作再…

使用 Verdaccio 構建自己的私有 npm 倉庫

前言 無論你是公司的開發者&#xff0c;還是個人開發者&#xff0c;你可能都聽說過或者使用過 npm&#xff0c;這是一個使用廣泛的 JavaScript 包管理器。但是&#xff0c;你是否遇到過以下的問題&#xff1a;你需要一個私有的包存放地方&#xff0c;或者你需要在離線環境下使…

HDU - 4348To the moon——主席樹+區間修改

HDU - 4348To the moon 【題目描述】 【題目分析】 題目中說明每次更新后時間都會加1&#xff0c;而且還會需要查詢以前的區間&#xff0c;還會需要返回以前的時間&#xff0c;所以是很裸的主席樹。區間查詢的話我們同樣需要用到lazy標記 通過這道題我發現線段樹的操作還是很靈…

進入一個目錄需要那些權限

1.文件訪問者的分類 文件的訪問者具體可分為以下幾類&#xff1a; (1)擁有者 (2)組擁有者 (3)其他用戶 這些都代表什么意思呢&#xff1f; 其中r表示只讀&#xff0c;w表示只寫&#xff0c;x表示可執行&#xff0c;第一個字母代表了文件的類型&#xff0c;其中文件類型可以分為…

Socket網絡編程--小小網盤程序(2)

http://www.cnblogs.com/wunaozai/p/3887728.html 這一節將不會介紹太多的技術的問題&#xff0c;這節主要是搭建一個小小的框架&#xff0c;為了方便接下來的繼續編寫擴展程序。本次會在上一小節的基礎上加上一個身份驗證的功能。 因為網盤程序不像聊天程序&#xff0c;網盤是…

Linux下的重要目錄

1.bin目錄 主要防止系統下的各種必備可執行文件 2./proc 目錄 這個目錄相當于Windows下的計算機系統信息查看以及進程動態查看&#xff0c;可以查看計算機信息&#xff0c;用來存放當前計算機上的進程信息 3./sys 目錄 (1)其中block目錄用于存放塊設備文件 (2)bus存放總線類型…

HDU - 6278 Just $h$-index主席樹+二分

HDU - 6278 Just hhh-index 【題目描述】 【題目分析】 題目要求在區間[l,r][l,r][l,r]內大于h的數不少于h個&#xff0c;對于這種最大化問題&#xff0c;我們應該想到二分。 最小情況顯然是1.最大情況顯然是r?l1r-l1r?l1&#xff0c;對于一個hhh&#xff0c;我們如何判斷能…

Socket網絡編程--小小網盤程序(3)

http://www.cnblogs.com/wunaozai/p/3891062.html 接上一小節&#xff0c;這次增加另外的兩張表&#xff0c;用于記錄用戶是保存那些文件。增加傳上來的文件的文件指紋&#xff0c;使用MD5表示。 兩張表如下定義: 1 create table files(2 fid int,3 filename varchar(64),4 md…

LInux下du, df, top, free, pstack, su, sudo, adduser, password命令

1.du命令&#xff1a;du [選項] 文件 (1)功能該命令是顯示指定文件以及下的所有文件占用系統數據塊的情況&#xff0c;如果沒有文件&#xff0c;默認為是當前工作目錄 -a ???顯示所有文件對系統數據塊的使用情況 -b ???顯示數據塊大小時以字節為基本單位 -c ???除了顯…

HDU - 5919 Sequence II——主席樹+區間種類++逆序建樹

【題目描述】 HDU - 5919 Sequence II 【題目分析】 題目給定一個數組&#xff0c;每次查詢一個區間&#xff0c;找出區間內不同數字的個數x&#xff0c;然后輸出按出現順序第x/2向上取整個數字的位置。 按照要求&#xff0c;我們首先需要能夠找出給定區間不同的數字個數。 首…

Socket網絡編程--小小網盤程序(4)

http://www.cnblogs.com/wunaozai/p/3892729.html 在這一小節中實現了文件的下載&#xff0c;具體的思路是根據用戶的uid和用戶提供的文件名filename聯合兩張表&#xff0c;取得md5唯一標識符&#xff0c;然后操作這個標識符對應的文件發送給客戶端。 實現下載的小小網盤程序 …

靜態順序表的實現

實現對順序表的初始化&#xff0c;頭插&#xff0c;頭刪&#xff0c;尾插&#xff0c;尾刪&#xff0c; 任意下標的刪除&#xff0c; 任意下標處的的元素刪除&#xff0c;任意下標處的元素插入&#xff0c;任意元素的下標返回&#xff0c;任意下標處的元素返回&#xff0c; 刪除…

樹鏈剖分入門+HYSBZ - 1036樹的統計Count

今天學習了樹鏈剖分&#xff0c;記錄一下。 【題目背景】 HYSBZ - 1036樹的統計Count 【題目分析】 題目要求求任意結點之間路徑的和以及路徑上最大的結點&#xff0c;還有可能修改。如果正常做可能會很復雜&#xff08;我也不知道正常應該怎么做&#xff0c;應該要用到LCA什么…

Socket網絡編程--小小網盤程序(5)

http://www.cnblogs.com/wunaozai/p/3893469.html 各位好呀&#xff01;這一小節應該就是這個小小網盤程序的最后一小節了&#xff0c;這一節將實現最后的三個功能&#xff0c;即列出用戶在服務器中的文件列表&#xff0c;還有刪除用戶在服務器中的文件&#xff0c;最后的可以共…