JZOJ-senior-5943. 【NOIP2018模擬11.01】樹
阿新 • • 發佈:2018-11-08
Time Limits: 1000 ms Memory Limits: 262144 KB
Description
Input
第一行一個整數 n 表示序列長度, 接下來一行 n 個整數描述這個序列.
第三行一個整數 q 表示操作次數, 接下來 q 行每行一次操作, 格式同題目描述.
Output
輸出等同於操作 2, 3 次數之和的行數, 每行一個非負整數表示對應詢問的答案. 注意操作 2 的答案不需要進行取模.
Sample Input
Sample Input1
5
8 4 3 5 6
5
2 3 5
3 1 2
1 2 4 3
2 3 5
3 1 2
樣例 2
見下發檔案中的 ex_seg2.in/out.
Sample Output
Sample Output1
14
608
10
384
樣例 1 解釋
第三次操作後, 序列變為 [8, 0, 3, 1, 6].
Data Constraint
對於前 30% 的資料, n, q ≤ 100;
對於另 20% 的資料, 沒有操作 1;
對於另 20% 的資料, 沒有操作 3;
對於 100% 的資料, n, q ≤ 10^5, ai ≤ 10^9, k ≤ 2^30, 1 ≤ l ≤ r ≤ n.
Solution
每次修改只會讓數變小,一個數最多隻會被修改
次
我們用線段樹維護一個區間是否有修改的必要(用區間的或值來判斷),需要修改就暴力修改
對於操作三,把式子展開,再維護一個區間平方和就行了
時間複雜度
Code
#include<algorithm>
#include<cstdio>
#include<cctype>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#define ll long long
#define L x<<1
#define R L|1
using namespace std;
const int N=1e5+5,P=998244353;
int n,m,t,opl,opr,k,a[N];
struct node{ll s1; int s2,p;}tr[4*N];
inline void read(int &n)
{
int x=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
n=w?-x:x;
}
void update(int x)
{
tr[x].s1=tr[L].s1+tr[R].s1;
tr[x].s2=(tr[L].s2+tr[R].s2)%P;
tr[x].p=tr[L].p|tr[R].p;
}
void build(int x,int l,int r)
{
if(l==r)
{
tr[x].s1=a[l];
tr[x].s2=(ll)a[l]*(ll)a[l]%P;
tr[x].p=a[l];
return;
}
int mid=(l+r)>>1;
build(L,l,mid),build(R,mid+1,r);
update(x);
}
void modify(int x,int st,int en,int l,int r)
{
if(st==en)
{
tr[x].s1&=k;
tr[x].s2=(ll)tr[x].s1*(ll)tr[x].s1%P;
tr[x].p=tr[x].s1;
return;
}
int mid=(st+en)>>1;
if(r<=mid)
{
if((tr[L].p&k)<tr[L].p) modify(L,st,mid,l,r);
}
else if(l>mid)
{
if((tr[R].p&k)<tr[R].p) modify(R,mid+1,en,l,r);
}
else
{
if((tr[L].p&k)<tr[L].p) modify(L,st,mid,l,mid);
if((tr[R].p&k)<tr[R].p) modify(R,mid+1,en,mid+1,r);
}
update(x);
}
node ask(int x,int st,int en,int l,int r)
{
if(st==l&&en==r) return tr[x];
int mid=(st+en)>>1;
if(r<=mid) return ask(L,st,mid,l,r);
else if(l>mid) return ask(R,mid+1,en,l,r);
else
{
node b1=ask(L,st,mid,l,mid);
node b2=ask(R,mid+1,en,mid+1,r);
return (node){b1.s1+b2.s1,(b1.s2+b2.s2)%P,0};
}
}
int main()
{
freopen("seg.in","r",stdin);
freopen("seg.out","w",stdout);
read(n);
fo(i,1,n) read(a[i]);
build(1,1,n);
read(m);
fo(i,1,m)
{
read(t),read(opl),read(opr);
if(t==1)
{
read(k);
modify(1,1,n,opl,opr);
continue;
}
node e=ask(1,1,n,opl,opr);
ll ans=0;
if(t==2) ans=e.s1;
else
{
e.s1%=P,e.s2%=P;
ans=((ll)2*(ll)(opr-opl+1)%P*(ll)e.s2%P+(ll)2*(ll)e.s1%P*(ll)e.s1%P)%P;
}
printf("%lld\n",ans);
}
}