HDU 4578 변환 (세그먼트 트리 + 숙련 게으른 마크 지방 분권)

Yuanfang 아래의 질문에 의아해한다 :
n은 정수 1이 있습니다, 2, ..., 없음을. 이들의 초기 값은 작업 네 가지 종류가 있습니다 0입니다.
작업 1 : 도끼와 바깥까지의 각 번호에 C를 추가합니다. 즉, K <-a K + C, K = X, X + 1, ..., Y 변환을한다.
동작 2 : AX 및 AY까지의 각 숫자를 곱 하였다. 즉, k 번째 변환 <-ak × C, K = X, X + 1, ..., Y 할.
작업 3 : 변경 C에 도끼와 바깥 사이의 숫자 포함. 즉, k 번째 변환 <-c, K = X, X + 1, ..., Y 할.
작업 4 : 도끼와 바깥까지의 숫자 중 P 전력의 합을 가져옵니다. 즉, 도끼 P + A, X + 1 + ... + P (AY) (p)의 결과를 얻는다.
Yuanfang 그것을 수행하는 방법을 모르고있다. 그래서 그는 그에게 도움을 요청하고자합니다.
입력
에는 10 개 이상의 테스트 케이스가 없습니다.
각 경우에있어서, 첫 번째 행과 m은 정수 연산 N이 있다는 것을 의미하는 두 숫자 n 및 m을 포함한다. 1 <= N, m <= 100,000.
각각 다음과 m 라인의 동작을 포함한다. 3 동작도 1은 본 형태에 "XYC 1"또는 "2 XYC"또는 "3 XYC". "4 xyp"작업 4는이 형식으로되어 있습니다. (1 <= X <= Y <= N 1 <= C <= 10,000, 1 <= p <= 3)
0 0 인 입력 단부
출력
한 라인의 각 동작 4, 출력 한 정수 나타내는 결과. 대답은 매우 클 수있다. 10007로 나누었을 때 당신은 대답의 나머지를 계산해야
샘플 입력
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
샘플 출력
(307)
7489
문제 해결 방안 :
바로 기록을 넣어 법에 따라 경우, 게으른 마크가이 질문에 매우 복잡해야하지만 팔초의 주제에이 시간, 데이터도 매우 특별하다, 초기 데이터는 0이다. 우리가 직접 조작 동기 및주기 횟수 산출 할 수 있도록 이제 변경할 때마다, 간격 기간의 값이 동일해야
SUM = (L-R 및 LT +. 1) * A [RT] ^ P를 ; 참고 : 우리가 관심 게으른 마크를 각 업데이트와 합계를 지불해야한다.
코드 :

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=1e5+5;
const int mod=10007;
const int inf=1e9;
const long long onf=1e18;
#define me(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
#define lson p*2,l,mid
#define rson p*2+1,mid+1,r
#define PI 3.14159265358979323846
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int n,m;
struct segmenttree{
    int l,r;
    int dat,lasy;
}t[maxn<<2];
void pushup(int p){
    if(!t[p*2].lasy||!t[p*2+1].lasy)
        t[p].lasy=0;
    else if(t[p*2].dat!=t[p*2+1].dat)
        t[p].lasy=0;
    else {
        t[p].dat=t[p*2].dat=t[p*2+1].dat;
        t[p].lasy=1;
    }
}
void pushdown(int p){
  
    if(t[p].lasy){

        t[p*2].lasy=t[p*2+1].lasy=1;
         t[p*2].dat=t[p*2+1].dat=t[p].dat;
        t[p].lasy=0;
        
    }
}
void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){
         t[p].dat=0,t[p].lasy=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(p);
}
void change(int p,int l,int r,int op,int c){
    if(l<=t[p].l&&r>=t[p].r&&t[p].lasy){
        if(op==1) t[p].dat=(t[p].dat+c)%mod;
        if(op==2) t[p].dat=(t[p].dat*c)%mod;
        if(op==3) t[p].dat=c%mod;
        return ;

    }
   pushdown(p);
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid) change(p*2,l,r,op,c);
    if(r>mid) change(p*2+1,l,r,op,c);
    pushup(p);

}
int ask(int p,int l,int r,int x){
    if(l<=t[p].l&&r>=t[p].r&&t[p].lasy)
       { int ans=1;
       for(int i=1;i<=x;i++)
            ans=(ans*t[p].dat)%mod;
        ans=(ans*(t[p].r-t[p].l+1))%mod;
        return ans;
       }
    int mid=(t[p].l+t[p].r)>>1;
    pushdown(p);
    int ans=0;
    if(l<=mid) ans=(ans+ask(p*2,l,r,x))%mod;
    if(r>mid) ans=(ans+ask(p*2+1,l,r,x))%mod;
    return ans%mod;

}
int main()
{   while(~scanf("%d %d",&n,&m),n+n){
        build(1,1,n);
        int p,x,y,z;
        for(int i=1;i<=m;i++){
            scanf("%d %d %d %d",&p,&x,&y,&z);
            if(p<=3)change(1,x,y,p,z);
            else printf("%d\n",ask(1,x,y,z));
        }
}
}
   
게시 된 156 개 원래 기사 · 원의 찬양 9 · 전망 6525

추천

출처blog.csdn.net/weixin_43438700/article/details/103153032