教练给我们打的离线(
数据分治忘删,多 solve 一次,明明复杂度 O(n^3) 偏偏不想压空间 敬重桥廊
不挂的话,70+100+50+50,挂了是 70+100+0+0/cy
推销一下 https://www.cnblogs.com/RuntimeErr/p/16757799.html
A
神笔题,不说了,没意义。
B
你会想要树形 dp,但是你发现其实儿子的子树(除去儿子)对当前答案没有任何影响,于是你会想到我们可以钦定点,然后仅保留这个点和这个点的儿子,钦定这些点是否跳,来得到答案。不重不漏考虑其他点乱跳,即我们只是选取了其一部分来观察这一部分对答案的贡献而已。
然后你会发现你要枚举子集,然后你发现是异或,然后典中典,枚举位,组合数一下就可以了。
#include <bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=(int)(1e5+5),mod=(int)(1e9+7);
vector<int>g[N];
int n,a[N],v[N],sz[N],ans;
int fpow(int x,int y) {
if(y<=0) return 1;
int res=1; x%=mod;
while(y) {
if(y&1) res=res*x%mod;
y>>=1; x=x*x%mod;
} return res;
}
void dfs(int x,int ff) {
int tot=0; sz[x]=1;
for(int y:g[x]) {
if(y==ff) continue ;
dfs(y,x); sz[x]+=sz[y];
}
for(int y:g[x]) {
if(y==ff) continue ;
v[++tot]=a[y];
}
int qwq;
if(x==1) qwq=fpow(2,n-1-tot);
else qwq=fpow(2,n-2-tot);
int res=0;
if(x!=1) {
for(int i=0;i<=30;i++) {
int cnt1=0,cnt0=0;
for(int j=1;j<=tot;j++) {
if((v[j]>>i)&1) ++cnt1;
else ++cnt0;
}
if(cnt1>=1) {
res=(res+(1ll<<i)*cnt1%mod*(fpow(2,cnt0)-1)%mod)%mod;
res=(res+(1ll<<i)*(fpow(2,cnt1-1)-cnt1)%mod*fpow(2,cnt0)%mod)%mod;
}
}
}
for(int i=0;i<=30;i++) {
int cnt1=0,cnt0=0;
for(int j=1;j<=tot;j++) {
if((v[j]>>i)&1) ++cnt1;
else ++cnt0;
}
if((a[x]>>i)&1) {
res=(res+(1ll<<i)*(fpow(2,cnt0)-1)%mod)%mod;
if(cnt1>=2) {
res=(res+(1ll<<i)*(fpow(2,cnt1-1)-1)%mod*fpow(2,cnt0)%mod)%mod;
}
} else {
if(cnt1) {
res=(res+(1ll<<i)*fpow(2,cnt1-1)%mod*fpow(2,cnt0)%mod)%mod;
}
}
}
// cout<<x<<" "<<res*qwq<<'\n';
ans=(ans+res*qwq%mod)%mod;
}
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++) {
int x; cin>>x;
g[x].pb(i); g[i].pb(x);
}
dfs(1,0);
ans=(ans%mod+mod)%mod;
cout<<ans;
return 0;
}
D
假如你不会线段树维护分段函数,假如你不会不带 \(\log\) 的合并,建议跟我一样分块,但是块长和询问次数你要卡好。
显然我们有 \(B\log n=\dfrac{n}{B}+B\),解得 \(B=\sqrt{\dfrac{n}{\log n-1}}\),很厉害啊。
然后我试了一下 \(B=\sqrt{n}\),发现只能 55。充分说明了平衡的重要性(
#include <bits/stdc++.h>
//#define int long long
#define pb push_back
using namespace std;
const int N=(int)(3e5+5),M=5002;
struct node {
int op,x;
}a[N];
struct nd {
int L,R,b,lv,rv;
nd() {
}
nd(int xL,int xR,int xb,int xlv,int xrv) {
L=xL; R=xR; b=xb; lv=xlv; rv=xrv;
}
}val[M];
int n,q,bl,id[N],L[M],R[M];
int qry(int idx,int x) {
for(int i=L[idx];i<=R[idx];i++) {
if(a[i].op==1) x+=a[i].x;
else if(a[i].op==2) x=min(x,a[i].x);
else x=max(x,a[i].x);
} return x;
}
nd query(int idx) { // [L,R]N :y=x+b
int L=1,R=(int)(1e8),q1=qry(idx,1),q2=qry(idx,2),qR=qry(idx,R),qR1=qry(idx,R-1);
if(q1!=q2) { //3/1
if(qR!=qR1) {
int qwq=q1-1;
return nd(1,(int)(1e8),qwq,0,0);
} else {
int l=1,r=(int)(1e8),res=0,qwq=qR;
while(l<=r) {
int mid=(l+r)>>1;
if(qry(idx,mid)==qwq) res=mid,r=mid-1;
else l=mid+1;
}
// if(x>=res) return qwq;
int b=qry(idx,res-1)-(res-1);
return nd(1,res-1,b,0,qR);
}
} else {
if(qR!=qR1) {
int l=1,r=(int)(1e8),res=0,qwq=q1;
while(l<=r) {
int mid=(l+r)>>1;
if(qry(idx,mid)==qwq) res=mid,l=mid+1;
else r=mid-1;
}
// if(x<=res) return qwq;
int b=qry(idx,res+1)-(res+1);
return nd(res+1,(int)(1e8),b,q1,0);
} else {
int l=1,r=(int)(1e8),qwq=q1,res=0;
while(l<=r) {
int mid=(l+r)>>1;
if(qry(idx,mid)==qwq) res=mid,l=mid+1;
else r=mid-1;
}
L=res+1;
l=1; r=(int)(1e8); qwq=qR; res=0;
while(l<=r) {
int mid=(l+r)>>1;
if(qry(idx,mid)==qwq) res=mid,r=mid-1;
else l=mid+1;
}
R=res-1;
// if(L<=x&&x<=R) {
// qwq=qry(L)-L;
// return x+qwq;
// }
// if(x<L) return qry(1);
// if(x>R) return qry((int)(1e8));
qwq=qry(idx,L)-L;
return nd(L,R,qwq,q1,qR);
}
}
}
int queryx(int idx,int x) {
if(val[idx].L<=x&&x<=val[idx].R) return x+val[idx].b;
if(x<val[idx].L) return val[idx].lv;
return val[idx].rv;
}
int qryx(int x) {
for(int i=1;i<=id[n];i++) {
x=queryx(i,x);
}
return x;
}
signed main() {
// freopen("1.in","r",stdin);
// freopen("xgf.out","w",stdout);
cin.tie(0); ios::sync_with_stdio(false);
cin>>n; bl=sqrt(n/max(1,(int)log2(n)-1));
for(int i=1;i<=n;i++) {
cin>>a[i].op>>a[i].x; id[i]=(i-1)/bl+1;
}
for(int i=1;i<=id[n];i++) L[i]=(i-1)*bl+1,R[i]=i*bl;
for(int i=1;i<=id[n];i++) val[i]=query(i);
cin>>q;
while(q--) {
int op; cin>>op;
if(op!=4) {
int x,y; cin>>x>>y;
a[x].op=op; a[x].x=y;
val[id[x]]=query(id[x]);
} else {
int x; cin>>x;
cout<<qryx(x)<<'\n';
}
}
return 0;
}