HDU 4578 Transformation (선분 트 리 + 4 일간 신 제 + 상해)

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 operations. 
Operation 1: Add c to each number between a 
x and a 
y inclusive. In other words, do transformation a 
kk+c, k = x,x+1,…,y. 
Operation 2: Multiply c to each number between a 
x and a 
y inclusive. In other words, do transformation a 
kk×c, k = x,x+1,…,y. 
Operation 3: Change the numbers between a 
x and a 
y to c, inclusive. In other words, do transformation a 
k Operation 4: Get the sum of p power among the numbers between a 
x and a 
y inclusive. In other words, get the result of a 

p+a 
x+1 
p+…+a 

p. 
Yuanfang has no idea of how to do it. So he wants to ask you to help him. 
InputThere 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. 
OutputFor 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

문제 풀이:
나 는 단지 이 문제 가 매우 매혹적이다 고 말 할 수 있 을 뿐이다. 이 문 제 는 내 가 4 일 동안 계속해서 AC 를 만 들 었 는데 그 중에서 WA 는 3 페이지 를 만 들 었 고 모두 40 여 번 이 었 다. 코드 를 3 번 다시 쓰 고 여러 가지 다른 방법 으로 썼 다.결국 어 쩔 수 없 이 다른 사람의 블 로 그 를 보고 한 사내 의 글 에 따라 AC 가 되 었 다.피 를 토 하 다만약 에 플러스 표기 가 있 으 면 플러스 의 값 을 곱 해 야 할 수 에 곱 하고 마지막 으로 곱셈 표 시 를 처리 하 며 한 번 에 두 번 째, 두 번 째, 세 번 째 공식 은 수학 을 하 는 유 씨 가 밀 었 다.결 과 는 제 가 사례 를 봤 습 니 다. 제 가 측정 한 몇 팀 도 지 났 습 니까? WA 입 니까? 여러 가지 팬 들 이 아무리 수정 해도 WA 입 니 다. 나중에 한 사내 가 공식 을 미 루 지 않 고 세 번 저장 하지 않 은 것 을 보 았 습 니 다.방법 은 신기 하고 보통 3 개의 값 을 저장 하 는 것 보다 속도 가 훨씬 빠르다.
생각 을 말 하 다.
같은 tag 1 은 플러스 표 시 를 표시 하고 tag 2 는 곱 하기, tag 3 표시 등 을 표시 합 니 다. 의심 할 여지없이 아래로 업데이트 할 때 등 호의 우선 순위 가 가장 높 아야 합 니 다. 먼저 등호 표 시 를 처리 하고 플러스 와 곱 하기 표 시 를 0 과 1 (초기 값) 로 설정 한 다음 에 중점 을 두 었 습 니 다. 곱셈 표 시 를 처리 할 때 하위 구간 에 등호 표시 가 있 는 것 을 발견 하면 등호 표 시 를 직접 수정 합 니 다.그렇지 않 으 면 하위 구간 pushdwon 을 비 운 다음 에 이 하위 구간 표 시 를 합 니 다. 플러스 번 호 는 같 습 니 다. 하위 구간 에 등호 표시 가 있 으 면 등호 표 시 를 수정 합 니 다. 그렇지 않 으 면 하위 구간 pushdown 을 비 운 다음 에 이 하위 구간 표 시 를 합 니 다. 모든 작업 이 끝나 면 현재 구간 표 시 를 비 운 다음 에 수정 할 때 도 많 지 않 습 니 다. 이 구간 에 등호 표시 가 있 는 지 확인 합 니 다.어떤 경우 에는 등호 표 시 를 직접 수정 해 야 한다. 그렇지 않 으 면 pushdown 은 이 구간 표 시 를 비우 고 각종 표 시 를 한다. 조회 할 때 는 전체 알고리즘 의 정수 이다. 그 는 구간 을 조회 하려 는 자구 간 의 등호 표 시 를 초기 표시 가 아니 라 같은 숫자 일 때 멈 춘 다음 에 이 구간 의 값 을 되 돌려 각 구간 을 누적 하여 답 을 얻는다.처음에 나 는 시간 을 초과 할 줄 알 았 는데, 결 과 는 뜻밖에도 일반적인 알고리즘 보다 훨씬 빨 라 서, 큰 사람 을 경 배 하 였 다.
사내 블 로그:http://blog.csdn.net/cq_pf/article/details/47054667
코드:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define left k*2
#define right k*2+1
const int N=10007;
struct node
{
    int l,r;
    int tag1,tag2,tag3;//      ,  ,    
}t[100005*4];
int n;
void Build(int l,int r,int k)
{
    t[k].l=l;
    t[k].r=r;
    t[k].tag1=0;
    t[k].tag2=1;
    t[k].tag3=-1;
    if(l==r)
    {
        t[k].tag3=0;//       0
        return;
    };
    int mid=(l+r)/2;
    Build(l,mid,left);
    Build(mid+1,r,right);
}
void pushdown(int k)
{
    if(t[k].l==t[k].r)//          
        return;
    if(t[k].tag3!=-1)//    
    {
        t[left].tag3=t[right].tag3=t[k].tag3;//         
        t[left].tag2=t[right].tag2=1;
        t[left].tag1=t[right].tag1=0;//         
        t[k].tag3=-1;
        return;
    }
    if(t[k].tag2!=1)//    
    {
        if(t[left].tag3!=-1)//          ,        
            t[left].tag3=(t[left].tag3*t[k].tag2)%N;
        else//          ,       
        {
            pushdown(left);
            t[left].tag2=(t[left].tag2*t[k].tag2)%N;
        }
        if(t[right].tag3!=-1)//       
            t[right].tag3=(t[right].tag3*t[k].tag2)%N;
        else
        {
            pushdown(right);
            t[right].tag2=(t[right].tag2*t[k].tag2)%N;
        }
        t[k].tag2=1;
    }
    if(t[k].tag1!=0)//      ,       
    {
        if(t[left].tag3!=-1)
            t[left].tag3=(t[left].tag3+t[k].tag1)%N;
        else
        {
            pushdown(left);
            t[left].tag1=(t[left].tag1+t[k].tag1)%N;
        }
        if(t[right].tag3!=-1)
            t[right].tag3=(t[right].tag3+t[k].tag1)%N;
        else
        {
            pushdown(right);
            t[right].tag1=(t[right].tag1+t[k].tag1)%N;
        }
        t[k].tag1=0;//    
    }
}
void update(int l,int r,int v,int d,int k)
{
    if(t[k].l==l&&t[k].r==r)
    {
        if(d==1)
        {
            if(t[k].tag3!=-1)//       ,         
            {
                t[k].tag3=(t[k].tag3+v%N)%N;
            }
            else
            {
                pushdown(k);//       ,    
                t[k].tag1=(t[k].tag1+v%N)%N;
            }
        }
        else if(d==2)//  
        {
            if(t[k].tag3!=-1)
            {
                t[k].tag3=(t[k].tag3*v%N)%N;
            }
            else
            {
                pushdown(k);
                t[k].tag2=(t[k].tag2*v%N)%N;
            }
        }
        else
        {
            t[k].tag3=v%N;
            t[k].tag1=0;
            t[k].tag2=1;
        }
        return;
    }
    pushdown(k);//    
    int mid=(t[k].l+t[k].r)/2;
    if(r<=mid)
        update(l,r,v,d,left);
    else if(l>mid)
        update(l,r,v,d,right);
    else
    {
        update(l,mid,v,d,left);
        update(mid+1,r,v,d,right);
    }
}
int query(int l,int r,int p,int k)//  
{
    if(t[k].l>=l&&t[k].r<=r&&t[k].tag3!=-1)//                    
    {
        int temp=1;
        for(int i=1;i<=p;i++)
            temp=(temp*t[k].tag3)%N;
        return ((t[k].r-t[k].l+1)%N*temp)%N;//       
    }
    pushdown(k);
    int mid=(t[k].l+t[k].r)/2;
    if(r<=mid)
        return query(l,r,p,left)%N;
    else if(l>mid)
        return query(l,r,p,right)%N;
    else
    {
        return (query(l,mid,p,left)+query(mid+1,r,p,right))%N;
    }
}
int main()
{
    int i,j,k,m,d,x,y,c;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        Build(1,n,1);
        for(i=0;i=1&&d<=3)
            {
                update(x,y,c,d,1);
            }
            else
            {
                printf("%d
",query(x,y,c,1)%N); } } } return 0; }

좋은 웹페이지 즐겨찾기