1. 程式人生 > >Hdu 4578 (線段樹)

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的最長連續字首長、最長連續後綴