树状数组
树状数组
搞点新东西。
树状数组维护最值
依旧维护 \((x-\operatorname{lowbit}(x),x]\) 的最值:
- 更新时每个包含此节点的都得更新一遍,每个包含此节点的块包含 \(\log n\) 个小块,共有 \(\log n\) 个包含此节点的块,\(O(\log^2n)\)
- 查询时满块直接查,不满一块直接
挂暴力与当前位置求最值。
int a[],t[];// a 表示原数组,t 是树状数组
void add(int pos,int chg){// 实则是修改
a[pos]=chg;
while(pos<=n){
t[pos]=chg;
for(int i=0;i<(pos&-pos);i++){
t[pos]=func(t[pos],t[pos-i])// 其中 func 是最值函数 max/min
}
}
}
void query(int l,int r){
int ans=a[r];
while(r>=l){
if(r-(r&-r)+1>=l){// 包含
ans=max(ans,t[r]);
r-=(r&-r);
}else{
ans=max(ans,a[r]);
--r;
}
}
}
哎是不是可重复贡献问题都可以这么做啊。。
例题:[USACO07JAN] Balanced Lineup G
y1s1,这题是不是没有修改。。
树状数组解决区间颜色数问题
这题我们发现全异或起来是奇数次的整数异或和,所以我们可以将区间去重取异或和再异或起来。
令 \(lst_x\) 表示 \(x\) 在数组 \(a\),当前下标 \(\boldsymbol{i}\) 前最后一次出现的位置。因为如果区间 \([j,i)\) 包含 \(x\),一定会包含 \(x\) 最后一次出现的位置。那么对于 \(a_i\),如果 \(lst_{a_i}\neq 0\),那么 \(\operatorname{add}(lst_{a_i},a_i)\) 即撤回(就本题树状数组维护的是异或和),再 \(\operatorname{add}((lst_{a_i}\gets i),a_i)\)。最后维护一个指针,如果指针指向的当前询问是类似 \([j,i]\)(\(\boldsymbol{i}\) 是当前下标!) 的询问,答案就是
\[\operatorname{query}(i,j)\oplus\displaystyle\bigoplus_{k=j}^ia_k
\]
后者用前缀和维护。
#define pbds
// #define many
#ifndef pbds
#include<bits/stdc++.h>
using namespace std;
using namespace __gnu_cxx;
#define pqueue priority_queue
#else
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
#define unordered_map __gnu_pbds::gp_hash_table
#define pqueue __gnu_pbds::priority_queue
typedef trie<string,null_type,trie_string_access_traits<>,pat_trie_tag,trie_prefix_search_node_update>Trie;
#endif
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,ll>pll;
typedef pair<ull,ull>pull;
template<size_t _Nw>
using arri=array<int,_Nw>;
template<size_t _Nw>
using arrl=array<ll,_Nw>;
template<typename Tp>
using heap=pqueue<Tp,greater<Tp>>;
mt19937 mt(chrono::system_clock::now().time_since_epoch().count());
mt19937_64 mt64(chrono::system_clock::now().time_since_epoch().count());
const bool mdsw=true;
const int mod=mdsw?998244353:(int)(1e9+7);
template<typename T=ll>
class fnw{
vector<T>t;
public:
fnw(size_t n=5e5){t.resize(n+5);}
void add(int pos,T v){
for(int i=pos;i<t.size();i+=(i&-i))t[i]^=v;
}
T query(int pos){
T ans=0;
for(int i=pos;i>0;i-=(i&-i))ans^=t[i];
return ans;
}
};
void solve(){
int n,q;
cin>>n;
vector<int>arr(n+1),s(n+1);
for(int i=1;i<=n;i++)cin>>arr[i],s[i]=s[i-1]^arr[i];
unordered_map<int,int>lst;
cin>>q;
vector<array<int,4>>Q(q);
for(int i=0;i<q;i++)cin>>Q[i][0]>>Q[i][1],Q[i][2]=i;
sort(Q.begin(),Q.end(),[](auto x,auto y){return x[1]<y[1];});
int now=0;
fnw t(n);
for(int i=1;i<=n&&now<q;i++){
if(lst[arr[i]])t.add(lst[arr[i]],arr[i]);
lst[arr[i]]=i;
t.add(lst[arr[i]],arr[i]);
while(now<q&&Q[now][1]==i)
Q[now][3]=(t.query(i)^t.query(Q[now][0]-1)^s[i]^s[Q[now][0]-1]),++now;
}
sort(Q.begin(),Q.end(),[](auto x,auto y){return x[2]<y[2];});
for(auto[l,r,id,ans]:Q)cout<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int oT_To;
for(
#ifdef many
cin>>oT_To
#else
oT_To=1
#endif
;oT_To--;solve());
long double some_Random_in_double=uniform_real_distribution<long double>(mt64(),mt64())(mt64);
if(some_Random_in_double==NAN||some_Random_in_double==INFINITY||abs(some_Random_in_double-some_Random_in_double)>114514)return 114514;
else if(1+1==3)exit(0x3f3f3f3f);
else if(clock()==66666)return clock();
else if(!time(nullptr))return 1919810;
else return 0;
}
再看这道题。
这个有点像,不过左端点、右端点严格递增,我就赛时想到了双指针加 kth 函数。
另:为什么这道题我
kth不开 O2 见祖宗了?!
例题:HH 的项链、BaoBao Loves Reading。
我绝不会说前者我用莫队、后者我用主席树过的。
HH 的项链:
#define pbds
// #define many
#ifndef pbds
#include<bits/stdc++.h>
using namespace std;
using namespace __gnu_cxx;
#define pqueue priority_queue
#else
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
#define unordered_map __gnu_pbds::gp_hash_table
#define pqueue __gnu_pbds::priority_queue
typedef trie<string,null_type,trie_string_access_traits<>,pat_trie_tag,trie_prefix_search_node_update>Trie;
#endif
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,ll>pll;
typedef pair<ull,ull>pull;
template<size_t _Nw>
using arri=array<int,_Nw>;
template<size_t _Nw>
using arrl=array<ll,_Nw>;
template<typename Tp>
using heap=pqueue<Tp,greater<Tp>>;
mt19937_64 mt64(chrono::system_clock::now().time_since_epoch().count());
namespace mo_algo{
#ifndef ONLINE_JUDGE
#define gc _getchar_nolock
#define pc _putchar_nolock
#else
#define gc getchar_unlocked
#define pc putchar_unlocked
#endif
template<typename read_type>
inline void read(read_type&t){
t=0;
int f=1;
#define nw c=gc()
char nw;
while(!isdigit(c)){if(c=='-')f=-1;nw;}
while(isdigit(c))t=(t<<3)+(t<<1)+c-48,nw;
#undef nw
if(!~f)t=-t;
}
template<typename read_type>
inline read_type read(){
read_type t=0;
int f=1;
#define nw c=gc()
char nw;
while(!isdigit(c)){if(c=='-')f=-1;nw;}
while(isdigit(c))t=(t<<3)+(t<<1)+c-48,nw;
#undef nw
if(!~f)t=-t;
return t;
}
template<typename rdtype,typename...read_type>
inline void read(rdtype&rd,read_type&...args){
read(rd);
read(args...);
}
template<typename write_type>
inline void write(write_type t){
static stack<char,vector<char>>sta;
do sta.push(48|t%10);while(t/=10);
while(!sta.empty())pc(sta.top()),sta.pop();
}
template<typename wttype,typename...write_type>
inline void write(wttype wt,write_type...args){
write(wt);
pc(' ');
write(args...);
}
static ll blk;
static int n,q;
struct node{
int l,r,id;
bool operator<(const node&nd)const{
if(l/blk!=nd.l/blk)return l<nd.l;
return((l/blk)&1?r>nd.r:r<nd.r);
}
};
static int cnt=0;
static const ll maxn=1e6+5;
static int occ[maxn],vec[maxn];
static node que[maxn];
static int ans[maxn],from[maxn],ttt;
inline void solve(){
read(n);
blk=max(sqrt(n),1.0);
for(register int i=0;i<n;++i)read(vec[i]),from[vec[i]]?vec[i]=from[vec[i]]:vec[i]=from[vec[i]]=++ttt;
read(q);
for(register int i=0;i<q;++i)read(que[i].l,que[i].r),--que[i].l,--que[i].r,que[i].id=i;
sort(que,que+q);
register int L=0,R=-1;
for(register int i=0;i<q;++i){
register int l=que[i].l,r=que[i].r,id=que[i].id;
while(L>l)--L,cnt+=(occ[vec[L]]==0),++occ[vec[L]];
while(R<r)++R,cnt+=(occ[vec[R]]==0),++occ[vec[R]];
while(L<l)cnt-=(occ[vec[L]]==1),--occ[vec[L]],++L;
while(R>r)cnt-=(occ[vec[R]]==1),--occ[vec[R]],--R;
ans[id]=cnt;
}
for(register int i=0;i<q;++i)write(ans[i]),pc('\n');
}
}
namespace fenwick{
template<typename T=ll>
class fnw{
vector<T>t;
public:
fnw(size_t n=5e5){t.resize(n+5);}
void add(int pos,T v){
for(int i=pos;i<t.size();i+=(i&-i))t[i]+=v;
}
T query(int pos){
T ans=0;
for(int i=pos;i>0;i-=(i&-i))ans+=t[i];
return ans;
}
};
void solve(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int n,q;
cin>>n;
vector<int>arr(n+1);
for(int i=1;i<=n;i++)cin>>arr[i];
unordered_map<int,int>lst;
cin>>q;
vector<array<int,4>>Q(q);
for(int i=0;i<q;i++)cin>>Q[i][0]>>Q[i][1],Q[i][2]=i;
sort(Q.begin(),Q.end(),[](auto x,auto y){return x[1]<y[1];});
int now=0;
fnw<>t(n);
for(int i=1;i<=n&&now<q;i++){
if(lst[arr[i]])t.add(lst[arr[i]],-1);
lst[arr[i]]=i;
t.add(lst[arr[i]],1);
while(now<q&&Q[now][1]==i)
Q[now][3]=(t.query(i)-t.query(Q[now][0]-1)),++now;
}
sort(Q.begin(),Q.end(),[](auto x,auto y){return x[2]<y[2];});
for(auto[l,r,id,ans]:Q)cout<<ans<<"\n";
}
}
int main(){
int oT_To;
for(
#ifdef many
cin>>oT_To
#else
oT_To=1
#endif
;oT_To--;(mt64()&1?fenwick::solve():mo_algo::solve()));
return 0;
}
浙公网安备 33010602011771号