Hdu 4578 (線段樹)
題目大意:n個數(初始為0)m個操作,操作型別有4中,操作1把區間的每個數+a,操作2把區間的每個數*a.,操作3把區間的每個數=a,操作4,查詢區間每個數p次方的和(1<=p<=3)
這個跟hdu3397有點類似。更新操作我還是分成兩類(1)= (2)*和+。 查詢操作:p只有三種可能,所以可以直接把次方,2次方,3次方的值存進去,一起更新
對於=更新操作:如果之前有*和+的標記,那可以忽略到*+操作,直接=操作,這個最簡單,sum1=val,sum2=val*val,sum3=val*val*val;
對於*+操作:如果之前有=標記,就不能忽略了,所以pushdown優先考略=操作。 *+操作可以一起(a*x+c).
注意:在*操作更新時,要一起更新+操作,因為(x+c)*a;
然後對於 (ax+c)^3=a^3*x^3+3*a^2*c*x^2+3*a*c^2*x+c^3,也就是root[t].sum3=a^3*root[t].sum3+3*a^2*c*root[t].sum2+3*a*c^2*root[t].sum1+c^3*(root[t].r-roo[t].l+1);
同理 root[t].sum2=root[t].sum2*a^2+root[t].sum1*c*2+c^2*(root[t].r-root[t].l+1);
root[t].sum1=root[t].sum1*a+c*(root[t].r-root[t].l+1);
注意:sum3,sum2,sum1在這個操作中的順序不能變。
struct node
{
int l,r;
int lazy1,lazy2,lazy3,p1,p2,p3;//lazy1加法,lazy2乘法,lazy3等於,p1一次方和,p2二次方和,p3三次方和;
}root[N*6];
Ps:一開始定義的long long ,結果TLE瘋了,後來把long long 全改成int,就過了,據說long long 比int 慢了一倍==
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
inline int input()
{
int r=0;
char c;
c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') r=r*10+c-'0',c=getchar();
return r;
}
#define N 100010
#define M 10007
struct node
{
int l,r;
int lazy1,lazy2,lazy3,p1,p2,p3;
}root[N*6];
inline void change_eq(int t,int val)
{
int l=root[t].r-root[t].l+1;
root[t].lazy1=0;
root[t].lazy2=1;
root[t].lazy3=val%M;
root[t].p1=val*l%M;
root[t].p2=val%M*val%M*l%M;
root[t].p3=val%M*val%M*val%M*l%M;
}
inline void change_add_mut(int t,int v1,int v2)
{
int l=root[t].r-root[t].l+1;
root[t].lazy2=root[t].lazy2*(v2%M)%M;
root[t].lazy1=(root[t].lazy1*v2%M+v1%M)%M;
root[t].p3=(root[t].p3%M*v2%M*v2%M*v2%M+v1%M*v1%M*v1%M*l%M+3*v2%M*v2%M*v1%M*root[t].p2%M+3*v2%M*v1%M*v1%M*root[t].p1%M)%M;
root[t].p2=(root[t].p2%M*v2%M*v2%M+v1%M*v1%M*l%M+2*v2%M*v1%M*root[t].p1%M)%M;
root[t].p1 =(v2 *root[t].p1%M +v1%M*l%M)%M;
}
inline void pushup(int t)
{
root[t].p1=(root[t*2].p1%M+root[t*2+1].p1%M)%M;
root[t].p2=(root[t*2].p2%M+root[t*2+1].p2%M)%M;
root[t].p3=(root[t*2].p3%M+root[t*2+1].p3%M)%M;
}
inline void pushdown_eq(int t)
{
if(root[t].l==root[t].r) return;
if(root[t].lazy3!=0)
{
change_eq(t*2,root[t].lazy3);
change_eq(t*2+1,root[t].lazy3);
root[t].lazy3=0;
}
}
inline void pushdown_add_mut(int t)
{
if(root[t].l==root[t].r) return;
if(root[t].lazy1!=0||root[t].lazy2!=1)
{
change_add_mut(t*2,root[t].lazy1,root[t].lazy2);
change_add_mut(t*2+1,root[t].lazy1,root[t].lazy2);
root[t].lazy1=0;
root[t].lazy2=1;
}
}
inline void build_tree(int t,int x,int y)
{
root[t].l=x;
root[t].r=y;
root[t].p1=root[t].p2=root[t].p3=0;
root[t].lazy1=root[t].lazy3=0;
root[t].lazy2=1;
if(x==y) return;
int m=(x+y)>>1;
build_tree(t*2,x,m);
build_tree(t*2+1,m+1,y);
}
inline void Modefiy_eq(int t,int x,int y,int val)
{
int l=root[t].l;
int r=root[t].r;
if(l==x&&r==y)
{
change_eq(t,val);
return;
}
pushdown_eq(t);
pushdown_add_mut(t);
int m=(l+r)>>1;
if(x<=m) Modefiy_eq(t*2,x,min(m,y),val);
if(y>m) Modefiy_eq(t*2+1,max(x,m+1),y,val);
pushup(t);
}
inline void Modefiy_add_mut(int t,int x,int y,int val,int op)
{
int l=root[t].l;
int r=root[t].r;
if(l==x&&r==y)
{
val%=M;
if(op==1)
{
int l=root[t].r-root[t].l+1;
root[t].lazy1=(root[t].lazy1+val)%M;
root[t].p3=(root[t].p3%M+3*val%M*root[t].p2%M+3*val%M*val%M*root[t].p1%M+val%M*val%M*val%M*l%M)%M;
root[t].p2=(root[t].p2%M+root[t].p1%M*2*val%M+val%M*val%M*l%M)%M;
root[t].p1=(root[t].p1+val*l%M)%M;
}
else if(op==2)
{
root[t].lazy1 =(root[t].lazy1*val%M)%M;
root[t].lazy2 =(root[t].lazy2*val%M)%M;
root[t].p1=(root[t].p1%M*val%M)%M;
root[t].p2=(root[t].p2%M*val%M*val%M)%M;
root[t].p3=(root[t].p3%M*val%M*val%M*val%M)%M;
}
return;
}
pushdown_eq(t);
pushdown_add_mut(t);
int m=(l+r)>>1;
if(x<=m) Modefiy_add_mut(t*2,x,min(m,y),val,op);
if(y>m) Modefiy_add_mut(t*2+1,max(m+1,x),y,val,op);
pushup(t);
}
inline int query(int t,int x,int y,int op)
{
int l=root[t].l;
int r=root[t].r;
if(l==x&&r==y)
{
if(op==1) return root[t].p1%M;
else if(op==2) return root[t].p2%M;
else if(op==3) return root[t].p3%M;
}
pushdown_eq(t);
pushdown_add_mut(t);
int m=(l+r)>>1;
int ans=0;
if(x<=m) ans+=query(t*2,x,min(m,y),op),ans%=M;
if(y>m) ans+=query(t*2+1,max(x,m+1),y,op),ans%=M;
return ans%M;
}
int n,m,op,x,y,z;
int main()
{
while(1)
{
n=input(),m=input();
if(n==0&&m==0) break;
build_tree(1,1,n);
while(m--)
{
op=input(),x=input(),y=input(),z=input();
if(op==1) Modefiy_add_mut(1,x,y,z,1);
else if(op==2) Modefiy_add_mut(1,x,y,z,2);
else if(op==3) Modefiy_eq(1,x,y,z);
else if(op==4) printf("%d\n",query(1,x,y,z));
}
}
return 0;
}
相關推薦
K - Transformation HDU - 4578(線段樹)
Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operati
Hdu 4578 (線段樹)
題目連結 題目大意:n個數(初始為0)m個操作,操作型別有4中,操作1把區間的每個數+a,操作2把區間的每個數*a.,操作3把區間的每個數=a,操作4,查詢區間每個數p次方的和(1<=p<=3) 這個跟hdu3397有點類似。更新操作我還是分成兩類(1)=
HDU 4027(線段樹)
提前 線段樹 都是 ace href 操作 代碼 處理 限制 HDU4027 題意:操作指令為0時,對區間[x,y]之間的數字進行開平方;指令為1的時候,對區間[x,y]之間的數字求和並輸出; 思路:線段樹處理就OK了,但是64位內的數最多開8次平方就為1了(開始不信,試了
LCIS HDU - 3308(線段樹)
Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting from 0) Q A B: output the length of the longest conse
L - Vases and Flowers HDU - 4614(線段樹)
Problem Description Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some
HDU 3333 (線段樹)
題意: 詢問一個區間中的不同數的和,例如 1 1 1 2 3 這個區間的和為6 分析: 離線處理,按照右區間端點值進行排序,然後記錄之前這個點是否出現過進行更改。然後最後查詢區間和。 處理完後就是很普通的線段樹單點操作區間求和。 #include<bits/s
HDU 6406(線段樹)
傳送門 題面: Taotao Picks Apples Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s):
HDU 6447(線段樹)
傳送門 題面: YJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the
hdu-4578-Transformation-線段樹(區間更新區間求和,多lazy,絕世好題)
Time limit 8000 msMemory limit 65536 kB Yuanfang is puzzled with the question below: There
HDU 5172 GTY's gay friends (線段樹)
ace tac 分享 log 沒有 http inf hdu algorithm 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5172 題意: 給你一個n個數的數組,m次詢問,詢問在[L, R] 這個區間裏面有沒有
Tunnel Warfare HDU - 1540(線段樹最長連續區間)
ont div n) pan Go build lse ons #define 題意: 一條線上的點,D x是破壞這個點,Q x是表示查詢以x所在的最長的連續的點的個數,R是恢復上一次破壞的點。 解析: 線段樹結點 設置一個 lq記錄區間左端點開始的最大連續個數,
Can you answer these queries? HDU - 4027(線段樹+技巧)
fin 題意 ios fff PE sqrt += 長度 scan 題意:給一個數組序列, 數組長度為100000 兩種操作: 一種操作是將某一個固定區間所有數開方(向下取整) 另一種操作是詢問某個區間的所有數字之和。 由於數不超過263,因此開個七八次就變成1,由於只有
HDU 1540 Tunnel Warfare(線段樹)
題意:一條線上的點,D x是破壞這個點,Q x是表示查詢以x所在的最長的連續的點的個數,R是恢復上一次破壞的點。 分析:還是最大連續區間的板題,不過就是變成了單個節點進行更新。直接套用板子稍微更改就好, #include<cstdio> #include<cstring&g
2018 Multi-University Training Contest hdu 6315 Naive Operations(線段樹)
題意 有兩個數列a和b,a的初始值為0,b陣列是1~n的一個排列,有兩個操作: 1. 將a陣列區間[l,r]的每個數+1。 2. 輸出Σa[i]/b[i](l<=i<=r)Σa[i]/b[i](l<=i<=r)。 題解 由於運算元一共10^
J - Assign the task HDU - 3974(線段樹 + dfs序)
There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole compa
HDU 1540(線段樹+區間合並)學習記錄
div uil hdu 1540 hup fin bsp play names http 學習了線段樹的新姿勢,記錄一下 參考blog:https://blog.csdn.net/sunyutian1998/article/details/79618316 query的
HDU 1540(線段樹+區間合併)學習記錄
學習了線段樹的新姿勢,記錄一下 參考blog:https://blog.csdn.net/sunyutian1998/article/details/79618316 query的時候m-ql+1和qr-m寫成了m-l+1、r-m,wa了幾發之後才找到bug 錯誤樣例: 10 1Q 5 wrong
HDU 640 Taotao Picks Apples & FJUT3592 做完其他題後才能做的題(線段樹)題解
題意(FJUT翻譯HDU): 錢陶陶家門前有一棵蘋果樹。 秋天來了,樹上的n個蘋果成熟了,淘淘會去採摘這些蘋果。 到園子裡摘蘋果時,淘淘將這些蘋果從第一個蘋果掃到最後一個。 如果當前的蘋果是第一個蘋果,或者它嚴格高於之前選擇的蘋果,那麼淘淘將採摘這個蘋果; 否則,他不會選擇。
hdu 5700 區間交(線段樹)
好久沒做這種題都不太會了。想法是先排序然後就大概有個方向了。 #include <stdio.h> #include <string.h> #include <ctime> #include <stack> #include <str
HDU 1540(線段樹區間合併+維護連續0或1)
題意:1-n個地道,m個次操作,D代表摧毀第i個地道,Q代表查詢包含第i個地道的最大連續地道數目,並輸出。R代表修復最近摧毀的那個地道; 思路:這題利用了線段樹的相鄰結點區間是連續的特性,而且是維護連續的1,所以用llen、rlen、len陣列分別表代表當前結點的1的最長連續字首長、最長連續後綴