1. 程式人生 > >p3792 由乃與大母神原型和偶像崇拜(思維+線段樹)

p3792 由乃與大母神原型和偶像崇拜(思維+線段樹)

要求
1.修改x位置的值為y
2.查詢區間l,r是否可以重排為值域上連續的一段

可以,很lxl
然後一開始思考合併區間,但是發現可以重排序,GG
然後想了特殊性質,比如求和,但是顯然可以被叉
這時候我覺得要把每個數都儘量特殊化,讓不同數字差異化之後和儘量不同,考慮維護一個立方和
求1到n的立方和有這樣的公式
\({( \frac{n*(n+1)}{2}) }^2\)
然後就維護立方和,為了防止爆long long取模
注意

  • 除2要乘2的逆元
  • 維護sum要取模
    然後沒了
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MOD = 1e9+7;
long long sum[500100<<2],minx[500100<<2],maxx[500100<<2],a[500100],n,m;
struct ansNode{
    long long s,MIN,MAX;
};
void pushup(int o){
    sum[o]=(sum[o<<1]+sum[o<<1|1])%MOD;
    minx[o]=min(minx[o<<1],minx[o<<1|1]);
    maxx[o]=max(maxx[o<<1],maxx[o<<1|1]);
}
void build(int l,int r,int o){
    if(l==r){
        maxx[o]=a[l];
        minx[o]=a[l];
        sum[o]=a[l]%MOD*a[l]%MOD*a[l]%MOD;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,o<<1);
    build(mid+1,r,o<<1|1);
    pushup(o);
}
void set(int L,int R,int o,int pos,int c){
    if(L==R){
        maxx[o]=c;
        minx[o]=c;
        sum[o]=c%MOD*c%MOD*c%MOD;
        return;
    }
    int mid=(L+R)>>1;
    if(pos<=mid)
        set(L,mid,o<<1,pos,c);
    else
        set(mid+1,R,o<<1|1,pos,c);
    pushup(o);
}
ansNode query(int L,int R,int l,int r,int o){//first sum second min
    if(L<=l&&r<=R){
        return (ansNode){sum[o],minx[o],maxx[o]};
    }
    int mid=(l+r)>>1;
    ansNode ans;
    ans.s=0;
    ans.MIN=1e9;
    ans.MAX=0;
    if(L<=mid){
        ansNode midx;
        midx=query(L,R,l,mid,o<<1);
        ans.s=(ans.s+midx.s)%MOD;
        ans.MIN=min(ans.MIN,midx.MIN);
        ans.MAX=max(ans.MAX,midx.MAX);
    }
    if(R>mid){
        ansNode midx;
        midx=query(L,R,mid+1,r,o<<1|1);
        ans.s=(ans.s+midx.s)%MOD;
        ans.MIN=min(ans.MIN,midx.MIN);
        ans.MAX=max(ans.MAX,midx.MAX);
    }
    return ans;
}
long long sig(long long n){
    return ((n*(n+1)%MOD*500000004%MOD)%MOD)*((n*(n+1)%MOD*500000004%MOD)%MOD)%MOD;
}
bool isright(int L,int R){
    ansNode p=query(L,R,1,n,1);
    return (((sig(p.MAX)-sig(p.MIN-1))%MOD+MOD)%MOD==p.s);
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,n,1);
    for(int i=1;i<=m;i++){
        int opt,x,y;
        scanf("%d %d %d",&opt,&x,&y);
        if(opt==1)
            set(1,n,1,x,y);
        else
            printf("%s\n",(isright(x,y))?"damushen":"yuanxing");
    }
    return 0;
}