专栏文章
CF1957
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mio1cl6r
- 此快照首次捕获于
- 2025/12/02 11:45 3 个月前
- 此快照最后确认于
- 2025/12/02 11:45 3 个月前
CF1957
D
Description
给定序列 ,求满足以下条件的三元组 的数量:
-
.
-
.
其中 表示 。
。
Solution
化简原式: 。
将区间异或转化为前缀异或,定义 为前 个数的异或和。
转化为 。
考虑 什么时候成立,我们只关注 的最高位 ,若 的第 位为 则不等式成立。
我们枚举 ,对于所有 ,求有多少个 的第 位为 ,这可以预处理前缀和后缀和。
Code
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,M=35;
int T,n,a[N],s[N],pr[N][M][2],sf[N][M][2],ans;
int read(){
int k=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
k=k*10+ch-'0',ch=getchar();
return k;
}
signed main(){
T=read();
while(T--){
n=read();
for(int i=1;i<=n;i++)
a[i]=read(),s[i]=s[i-1]^a[i];
for(int i=0;i<n;i++){
for(int j=0;j<=30;j++){
pr[i][j][0]=pr[i-1][j][0];
pr[i][j][1]=pr[i-1][j][1];
if(s[i]&(1<<j))
pr[i][j][1]++;
else
pr[i][j][0]++;
}
}
for(int j=0;j<=30;j++)
sf[n+1][j][0]=0,sf[n+1][j][1]=0;
for(int i=n;i>=1;i--){
for(int j=0;j<=30;j++){
sf[i][j][0]=sf[i+1][j][0];
sf[i][j][1]=sf[i+1][j][1];
if(s[i]&(1<<j))
sf[i][j][1]++;
else
sf[i][j][0]++;
}
}
ans=0;
for(int i=1;i<=n;i++){
int t=0;
while(a[i]>1){
a[i]=(a[i]>>1);
t++;
}
ans+=pr[i-1][t][0]*sf[i][t][0]+pr[i-1][t][1]*sf[i][t][1];
}
printf("%lld\n",ans);
}
return 0;
}
E
神秘组合数学题,未完待续。
F
Description
给定一棵树,点有点权,每次询问给出 ,请你找到至多 个数,满足其在 路径上出现次数和在 路径上出现次数不同。
,。
Solution
对于一棵树上的路径,我们可以通过主席树来差分求出一条路径上每个数的出现次数。
现在的问题形如给定两棵线段树,快速找到 个权值不同的叶子节点。
如果我们能快速判断两棵子树是否相等,只在子树不同时递归,时间复杂度就是 。
考虑使用哈希,用线段树维护当前区间的哈希值即可完成本题。
为了方便,代码中使用了加减哈希。
Code
CPP#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N=2e5+5,M=1e5;
struct node{
int ls,rs,sum;
}tr[N<<5];
struct ask{
int x,y,t,ft;
};
int n,q,mx,a[N],cnt,ans[N];
int idx,lg[N],pos[N],st[N][20];
int ha[N],len,fa[N],rt[N];
vector<int>e[N];
int read(){
int k=0;
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
while(ch>='0'&&ch<='9')
k=k*10+ch-'0',ch=getchar();
return k;
}
void dfs1(int x,int y){
pos[x]=++idx,st[idx][0]=x,fa[x]=y;
for(int i:e[x]){
if(i==y)
continue;
dfs1(i,x);
st[++idx][0]=x;
}
}
int qmax(int x,int y){
return (pos[x]<pos[y]?x:y);
}
void init(){
for(int i=2;i<=(n<<1);i++)
lg[i]=lg[i>>1]+1;
for(int j=1;j<=18;j++)
for(int i=1;i+(1<<j)-1<(n<<1);i++)
st[i][j]=qmax(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int lca(int x,int y){
x=pos[x],y=pos[y];
if(x>y) swap(x,y);
int k=lg[y-x+1];
return qmax(st[x][k],st[y-(1<<k)+1][k]);
}
void pushup(int k){
tr[k].sum=tr[tr[k].ls].sum+tr[tr[k].rs].sum;
}
void modify(int &k,int p,int l,int r,int x){
k=++len;
tr[k]=tr[p];
if(l==r){
tr[k].sum+=ha[l];
return;
}
int mid=(l+r)>>1;
if(x<=mid) modify(tr[k].ls,tr[p].ls,l,mid,x);
if(mid+1<=x) modify(tr[k].rs,tr[p].rs,mid+1,r,x);
pushup(k);
}
int qsum(ask a){
return tr[a.x].sum+tr[a.y].sum-tr[a.t].sum-tr[a.ft].sum;
}
ask qls(ask a){
return {tr[a.x].ls,tr[a.y].ls,tr[a.t].ls,tr[a.ft].ls};
}
ask qrs(ask a){
return {tr[a.x].rs,tr[a.y].rs,tr[a.t].rs,tr[a.ft].rs};
}
void solve(ask k,ask p,int l,int r){
if(cnt==mx) return;
if(l==r){
ans[++cnt]=l;
return;
}
int mid=(l+r)>>1;
if(qsum(qls(k))!=qsum(qls(p)))
solve(qls(k),qls(p),l,mid);
if(qsum(qrs(k))!=qsum(qrs(p)))
solve(qrs(k),qrs(p),mid+1,r);
}
void dfs2(int x){
modify(rt[x],rt[fa[x]],1,M,a[x]);
for(int i:e[x]){
if(i==fa[x])
continue;
dfs2(i);
}
}
signed main(){
mt19937 myrand(time(nullptr));
int u,v,u1,u2,v1,v2;
for(int i=1;i<=M;i++)
ha[i]=myrand();
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<n;i++){
u=read(),v=read();
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1,0);
init();
dfs2(1);
q=read();
for(int i=1;i<=q;i++){
u1=read(),v1=read(),u2=read(),v2=read(),mx=read();
cnt=0;
solve({rt[u1],rt[v1],rt[lca(u1,v1)],rt[fa[lca(u1,v1)]]},{rt[u2],rt[v2],rt[lca(u2,v2)],rt[fa[lca(u2,v2)]]},1,M);
printf("%llu ",cnt);
for(int j=1;j<=cnt;j++)
printf("%llu ",ans[j]);
printf("\n");
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...