給定乙個數列a,你需要支援的操作:區間and,區間or,詢問區間最大值
一行兩個整數n,m,表示數列長度和操作個數。
接下來一行有n個整數,第i個數表示ai。
接下來m行,每一行均為以下三種操作中的一種
1 l r val:ai=ai and val(l≤i≤r)
2 l r val:ai=ai or val(l≤i≤r)
3 l r:max(l≤i≤r)
對於每乙個3操作,輸出一行整數表示對應的答案
8 6
4 0 5 7 2 9 12 8
2 2 5 15
1 3 5 2
3 5 7
1 5 7 12
2 1 6 4
3 2 6
12
15
對於20%資料,n,m≤3000
另有20%資料,1,2操作中l=r
另有20%資料,3操作中l=r
對於100%資料,1≤n,m≤100000,0≤ai,val≤1e9
保證所有操作中1≤l≤r≤n
區間and操作相當於將區間中所有數的某些位全變成0,區間or操作相當於將區間中所有數的某些位全變成1。
線段樹每個節點維護區間and和以及區間or和,還要維護乙個and標記乙個or標記以及區間最大值。
標記的先後順序是先and後or。
區間操作先找到區間,如果區間中所有的數要修改的那些位已經全相同,直接打上標記後返回。否則遞迴處理子區間。
#include#define maxn 100010
#define inf 0x7fffffff
#define lc rt<<1
#define rc rt<<1|1
namespace io
inline int qr()
while(ch>='0'&&ch<='9')
return rev?-x:x;}
}using namespace io;
using namespace std;
int n,q,tago[maxn<<2],taga[maxn<<2],vo[maxn<<2],va[maxn<<2],ma[maxn<<2],a[maxn];
inline void up(int rt)
inline void putand(int rt,int x)
inline void putor(int rt,int x)
inline void down(int rt)
if(tago[rt])
}void build(int l,int r,int rt)
int mid=(l+r)>>1;
build(l,mid,lc);build(mid+1,r,rc);
up(rt);
}void modify(int l,int r,int l,int r,int rt,int x,bool flag)
} else
} } down(rt);
int mid=l+r>>1;
if(l<=mid)modify(l,r,l,mid,lc,x,flag);
if(r>mid)modify(l,r,mid+1,r,rc,x,flag);
up(rt);
}int query(int l,int r,int l,int r,int rt)
int op,x,y,z;
int main()
return 0;
}
cogs2638 數列操作 雙標記線段樹
題目大意 給定乙個數列a,你需要支援的操作 區間and,區間or,詢問區間最大值 解題關鍵 1 雙標記線段樹,注意優先順序 超時 當涉及多重標記時,定義出標記的優先順序,修改操作時用優先順序高 先下放 的修正優先順序低 後下放 的來保證標記的正確性。同時維護了區間and,區間or include i...
COGS 2964 數列操作
傳送門 題目描述 給定長度均為 n nn 的數列 a,b a,ba,b,其中 b bb 數列為 1 11 n nn 的全排列,a aa 數列全為 000。你需要支援 q qq 次操作,操作分為 add addad d 和 que ry query quer y 兩種。其中 x x x 表示對 x x...
COGS 2632 數列操作d
傳送門 題目描述 乙個長度為 n nn 的序列,一開始序列數的權值都是 0 00,有 m mm 次操作 支援兩種操作 1 11l llrrrx xx,給區間 l ll r rr 內位置為 pos pospo s 的數加上 po s l x pos l x pos l x000l llr rr,查詢區...