結果
| 問題 |
No.2697 Range LIS Query
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-03-22 22:39:43 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 6,889 ms / 10,000 ms |
| コード長 | 5,272 bytes |
| コンパイル時間 | 3,257 ms |
| コンパイル使用メモリ | 231,328 KB |
| 最終ジャッジ日時 | 2025-02-20 12:11:28 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 15 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()
template<class T> bool chmax(T &a, T b){if (a < b){a = b;return true;} else return false;}
template<class T> bool chmin(T &a, T b){if (a > b){a = b;return true;} else return false;}
template <typename M, typename O, typename M::T (*mapping)(typename O::T, typename M::T)>
struct lazy_segment_tree {
using T = typename M::T;
using F = typename O::T;
public:
explicit lazy_segment_tree() {}
explicit lazy_segment_tree(int N) : lazy_segment_tree(std::vector<T>(N, M::e())) {}
explicit lazy_segment_tree(const std::vector<T>& v) {
int N = (int)v.size();
n = N;
size = 1;
log = 0;
while (size < N) {
size <<= 1;
log++;
}
data.resize(2 * size, M::e());
lazy.resize(size, O::e());
for (int i = 0; i < N; i++) data[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) update(i);
};
void set(int p, T x) {
assert(0 <= p && p < n);
p += size;
push_from_root(p);
data[p] = x;
update_to_root(p);
}
T get(int p) {
assert(0 <= p && p < n);
p += size;
push_from_root(p);
return data[p];
}
T prod(int l, int r) {
assert(0 <= l && l <= r && r <= n);
if (l == r) return M::e();
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
T vl = M::e(), vr = M::e();
while (l < r) {
if (l & 1) vl = M::op(vl, data[l++]);
if (r & 1) vr = M::op(data[--r], vr);
l >>= 1;
r >>= 1;
}
return M::op(vl, vr);
}
T all_prod() { return data[1]; }
void apply(int p, F f) {
assert(0 <= p && p < n);
p += size;
push_from_root(p);
data[p] = mapping(f, data[p]);
update_to_root(p);
}
void apply(int l, int r, F f) {
assert(0 <= l && l <= r && r <= n);
if (l == r) return;
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
int l2 = l, r2 = r;
while (l < r) {
if (l & 1) all_apply(l++, f);
if (r & 1) all_apply(--r, f);
l >>= 1;
r >>= 1;
}
l = l2;
r = r2;
for (int i = 1; i <= log; i++) {
if (((l >> i) << i) != l) update(l >> i);
if (((r >> i) << i) != r) update((r - 1) >> i);
}
}
private:
int n, size, log;
std::vector<T> data;
std::vector<F> lazy;
void update(int p) { data[p] = M::op(data[2 * p], data[2 * p + 1]); }
void all_apply(int k, F f) {
data[k] = mapping(f, data[k]);
if (k < size) lazy[k] = O::op(f, lazy[k]);
}
void push(int p) {
assert(0 <= p && p < size);
all_apply(2 * p, lazy[p]);
all_apply(2 * p + 1, lazy[p]);
lazy[p] = O::e();
}
void push_from_root(int p) {
for (int i = log; i >= 1; i--) push(p >> i);
}
void update_to_root(int p) {
for (int i = 1; i <= log; i++) update(p >> i);
}
};
struct Monoid{
using T=pair<int,vector<vector<int>>>;
static T op(T l,T r){
T V;
V.first=l.first+r.first;
(V.second).resize(4,vector<int>(4));
for(int i=0;i<4;i++){
for(int j=i;j<4;j++){
for(int k=i;k<=j;k++){
for(int m=k;m<=j;m++){
chmax(V.second[i][j],l.second[i][k]+r.second[m][j]);
}
}
}
}
return V;
}
static T e(){
return{0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}};
}
};
const int ID=-1;
struct O{
using T=int;
static T op(T l,T r){return(l==ID?r:l);}
static T e(){return ID;}
};
Monoid::T mapping(O::T f,Monoid::T x){
if(f==ID){
return x;
}else{
Monoid::T V;
V.first=x.first;
(V.second).resize(4,vector<int>(4));
V.second[f][f]=x.first;
return V;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin>>N;
vector<int>A(N);
for(int i=0;i<N;i++){
cin>>A[i];
A[i]--;
}
lazy_segment_tree<Monoid,O,mapping>seg(N);
for(int i=0;i<N;i++){
Monoid::T V;
V.first=1;
(V.second).resize(4,vector<int>(4));
V.second[A[i]][A[i]]=1;
seg.set(i,V);
}
int Q;
cin>>Q;
while(Q--){
int t;
cin>>t;
if(t==1){
int l,r;
cin>>l>>r;
l--;
r--;
Monoid::T V=seg.prod(l,r+1);
int ans=0;
for(int i=0;i<4;i++)for(int j=0;j<4;j++)chmax(ans,V.second[i][j]);
cout<<ans<<"\n";
}else{
int l,r,x;
cin>>l>>r>>x;
l--;
r--;
x--;
seg.apply(l,r+1,x);
}
}
}