[洛谷P3792] 由乃与大母神原型和偶像崇拜

https://daniu.luogu.org/problemnew/show/P3792

题意提要

给你一个序列a

每次两个操作:

1.修改x位置的值为y

2.查询区间l,r是否可以重排为值域上连续的一段

输入输出格式

输入格式:

第一行两个数n,m

第二行n个数表示a[i]

后面m行每行三个数opt x y,或者opt l r,代表操作

输出格式:

如果可以,输出“damushen”

否则输出“yuanxing”

输入输出样例

输入样例#1: 复制
5 5
1 2 3 4 5
2 1 5
2 2 3
2 3 3
1 3 6
2 3 5
输出样例#1: 复制
damushen
damushen
damushen
damushen

说明

对于30%的数据,n,m<=500

对于60%的数据,n,m<=100000

对于100%的数据,n,m<=500000

值域1e9

2s

思路

使用线段树,维护最大值,最小值,平方和,乘积;

对于一段区间如果(最大值-最小值==区间长度-1)&&(平方和or乘积==合法序列的平方和or乘积(这两个是等价的,为什么都用,hash碰撞QUQ)),

那么该区间合法。

代码实现

  1 #include<cstdio>
  2 #include<algorithm>
  3 const int maxn=1e6+10;
  4 const int mod=998244353;
  5 inline int min_(int x,int y){return x<y?x:y;}
  6 inline int max_(int x,int y){return x>y?x:y;}
  7 int n,m;
  8 int f[maxn<<2],g[maxn<<2],s[maxn],x[maxn],opt[maxn];
  9 int in[maxn<<2],ax[maxn<<2],ip[maxn<<2],iq[maxn<<2];
 10 struct nate{int x,ip;}dtt[maxn];
 11 bool comp(nate a,nate b){return a.x>b.x;}
 12 int FP(int x,int y){
 13     int now=1;
 14     while(y){
 15         if(y&1) now=(1ll*now*x)%mod;
 16         x=(1ll*x*x)%mod;
 17         y>>=1;
 18     }
 19     return now;
 20 }
 21 int IE(int x){return FP(x,mod-2);}
 22 void build(int k,int l,int r){
 23     if(l==r){
 24         in[k]=ax[k]=s[l];
 25         iq[k]=s[l];
 26         ip[k]=(1ll*s[l]*s[l])%mod;
 27         return;
 28     }
 29     int mid=l+r>>1,ls=k<<1,rs=ls|1;
 30     build(ls,l,mid);
 31     build(rs,mid+1,r);
 32     in[k]=min_(in[ls],in[rs]);
 33     ax[k]=max_(ax[ls],ax[rs]);
 34     iq[k]=(1ll*iq[ls]*iq[rs])%mod;
 35     ip[k]=(1ll*ip[ls]+ip[rs])%mod;
 36 }
 37 void change(int k,int l,int r,int ap,int at){
 38     if(l==r){
 39         in[k]=ax[k]=ip[k]=at;
 40         iq[k]=at;
 41         ip[k]=(1ll*at*at)%mod;
 42         return;
 43     }
 44     int mid=l+r>>1,ls=k<<1,rs=ls|1;
 45     if(ap<=mid) change(ls,l,mid,ap,at); 
 46     else change(rs,mid+1,r,ap,at);
 47     in[k]=min_(in[ls],in[rs]);
 48     ax[k]=max_(ax[ls],ax[rs]);
 49     iq[k]=(1ll*iq[ls]*iq[rs])%mod;
 50     ip[k]=(1ll*ip[ls]+ip[rs])%mod;
 51 }
 52 int xin,xax,xip,xiq,bj;
 53 void search(int k,int l,int r,int al,int ar){
 54     if(l==al&&r==ar){
 55         xin=min_(xin,in[k]);
 56         xax=max_(xax,ax[k]);
 57         xip=(1ll*xip+ip[k])%mod;
 58         xiq=(1ll*xiq*iq[k])%mod;
 59         return;
 60     }
 61     int mid=l+r>>1,ls=k<<1,rs=ls|1;
 62     if(al<=mid) search(ls,l,mid,al,min_(ar,mid));
 63     if(ar>mid) search(rs,mid+1,r,max_(al,mid+1),ar);
 64 }
 65 bool ok(int l,int r){
 66     xin=mod,xax=0,xip=0,xiq=1;
 67     search(1,1,n,l,r);
 68     if(xax-xin!=r-l) return 0;
 69     bj=(1ll*f[xax]-f[xin-1]+mod)%mod;
 70     if(bj!=xip) return 0;
 71     bj=(1ll*g[xax]*IE(g[xin-1]))%mod;
 72     if(bj!=xiq) return 0;
 73     return 1;
 74 }
 75 int main(){
 76     scanf("%d%d",&n,&m);
 77     for(int i=1;i<=n;i++){
 78         scanf("%d",&s[i]);
 79         dtt[i].x=s[i],dtt[i].ip=i;
 80     }
 81     for(int i=1;i<=m;i++){
 82         scanf("%d%d%d",&opt[i],&x[i],&s[n+i]);
 83         if(opt[i]==1) dtt[n+i].x=s[n+i],dtt[n+i].ip=n+i;
 84     }
 85     int top=1;g[0]=1;
 86     std::sort(dtt+1,dtt+n+m+1,comp);
 87     for(int i=1;dtt[i].x&&i<=n+m;i++){
 88         s[dtt[i].ip]=top;
 89         if(dtt[i+1].x==dtt[i].x-1) top++;
 90         if(dtt[i+1].x<dtt[i].x-1) top+=2;
 91     }
 92     for(int i=1;i<=top;i++) g[i]=(1ll*i*g[i-1])%mod;
 93     for(int i=1;i<=top;i++) f[i]=(1ll*i*i+f[i-1])%mod;
 94     build(1,1,n);
 95     for(int i=1;i<=m;i++){
 96         if(opt[i]==1) change(1,1,n,x[i],s[n+i]);
 97         else{
 98             if(ok(x[i],s[n+i])) puts("damushen");
 99             else puts("yuanxing");
100         }
101     }
102     return 0;
103 }

 

 

 

听说是套路题QUQ果然我做题太少了。。。

posted @ 2017-12-15 15:00  J_william  阅读(457)  评论(0编辑  收藏  举报