J. 二进制与、平方和

https://codeforces.com/gym/104095/problem/J

分析操作一

1&0=0 ,0&1=0,ai<=qmi(2,24),说明每个数最多操作25次

维护区间或和,orsum & x== orsum 就不用递归下去了

势能线段树code

// Problem: J. 二进制与、平方和
// Contest: Codeforces - 2020 CCPC Henan Provincial Collegiate Programming Contest
// URL: https://codeforces.com/gym/104095/problem/J
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const int N=3e5+9;
const int mod=998244353;
int a[N];
template<class T>
constexpr T power(T a, LL b) {
    T res = 1;
    for (; b; b /= 2, a *= a) {
        if (b % 2) {
            res *= a;
        }
    }
    return res;
}
 
template<int P>
struct MInt {
    int x;
    constexpr MInt() : x{} {}
    constexpr MInt(LL x) : x{norm(x % getMod())} {}
    
    static int Mod;
    constexpr static int getMod() {
        if (P > 0) {
            return P;
        } else {
            return Mod;
        }
    }
    constexpr static void setMod(int Mod_) {
        Mod = Mod_;
    }
    constexpr int norm(int x) const {
        if (x < 0) {
            x += getMod();
        }
        if (x >= getMod()) {
            x -= getMod();
        }
        return x;
    }
    constexpr int val() const {
        return x;
    }
    explicit constexpr operator int() const {
        return x;
    }
    constexpr MInt operator-() const {
        MInt res;
        res.x = norm(getMod() - x);
        return res;
    }
    constexpr MInt inv() const {
        assert(x != 0);
        return power(*this, getMod() - 2);
    }
    constexpr MInt &operator*=(MInt rhs) & {
        x = 1LL * x * rhs.x % getMod();
        return *this;
    }
    constexpr MInt &operator+=(MInt rhs) & {
        x = norm(x + rhs.x);
        return *this;
    }
    constexpr MInt &operator-=(MInt rhs) & {
        x = norm(x - rhs.x);
        return *this;
    }
    constexpr MInt &operator/=(MInt rhs) & {
        return *this *= rhs.inv();
    }
    friend constexpr MInt operator*(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res *= rhs;
        return res;
    }
    friend constexpr MInt operator+(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res += rhs;
        return res;
    }
    friend constexpr MInt operator-(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res -= rhs;
        return res;
    }
    friend constexpr MInt operator/(MInt lhs, MInt rhs) {
        MInt res = lhs;
        res /= rhs;
        return res;
    }
    friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
        LL v;
        is >> v;
        a = MInt(v);
        return is;
    }
    friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
        return os << a.val();
    }
    friend constexpr bool operator==(MInt lhs, MInt rhs) {
        return lhs.val() == rhs.val();
    }
    friend constexpr bool operator!=(MInt lhs, MInt rhs) {
        return lhs.val() != rhs.val();
    }
};
 
template<>
int MInt<0>::Mod =998244353;
 
template<int V, int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();
 
constexpr int P =998244353;
using Z = MInt<P>;
 
const int mxn = 2e5 + 10;
struct SNSEG{
	#define ll long long 
	#define tl(id) (id<<1)
	#define tr(id) (id<<1|1)
	#define li inline
	struct node{
		Z pfval;
		int orsum;
	}seg[N<<2];
	#define pushup(id) seg[id].pfval=seg[tl(id)].pfval+seg[tr(id)].pfval, seg[id].orsum=seg[tl(id)].orsum|seg[tr(id)].orsum;
	li int inrange(int L,int R,int l,int r){return L>=l && R<=r;}
	li int outofrange(int L,int R,int l,int r){return L>r || l>R;}
	li void build(int id,int l,int r){
		if(l==r){
			seg[id].pfval=1ll*a[l]*a[l];
			// seg[id].val=a[l];
			seg[id].orsum=a[l];
			return;
		}
		int mid=(l+r)>>1;
		build(tl(id),l,mid);
		build(tr(id),mid+1,r);
		pushup(id);
	}
	li Z query(int id,int L,int R,int l,int r){
		if(inrange(L,R,l,r)){
			return seg[id].pfval;
		}else if(!outofrange(L,R,l,r)){
			int mid=(L+R)>>1;
			return query(tl(id),L,mid,l,r)+query(tr(id),mid+1,R,l,r);
		}else{
			return 0;
		}
	}
	li void modify(int id,int L,int R,int l,int r,int x){
		if(L==R){
			// seg[id].val&=x;
			seg[id].orsum&=x;//修改
			seg[id].pfval=1ll*seg[id].orsum*seg[id].orsum;
			return;
		}
		int mid=(L+R)>>1;
		if(mid>=l && (seg[tl(id)].orsum&x)!=(seg[tl(id)].orsum)){
			modify(tl(id),L,mid,l,r,x);
		}
		if(mid<r && (seg[tr(id)].orsum&x)!=(seg[tr(id)].orsum)){
			modify(tr(id),mid+1,R,l,r,x);
		}
		pushup(id);
	}
}t;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	t.build(1,1,n);
	int q;
	cin>>q;
	for(int i=1;i<=q;i++){
		int op;
		cin>>op;
		if(op==1){
			int l,r,x;
			cin>>l>>r>>x;
			t.modify(1,1,n,l,r,x);
		}else{
			int l,r;
			cin>>l>>r;
			cout<<t.query(1,1,n,l,r)<<'\n';		
		}
		// for(int i=1;i<=n;i++){
			// cout<<t.ask(1,1,n,i)<<" ";
		// }
		// cout<<'\n';
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值