Xcpc训练题目若干(二)
题意:给定一个序列a以及一个k,构造一个x使(ai ^ x ) <=k的ai数量最多
思路:枚举每一个a,从高位到低位分类讨论
设该位为j , 那么有四种情况
- aj=1,k=1
- aj=1,k=0
- aj=0,k=1
- aj=0,k=0
前面的位a与x异或后与k相同,判断该位然后确定x的范围,然后差分
int pre[maxn];
void solve(){
int n,k;cin>>n>>k;
vector<int>a(n+1);rep(i,1,n)cin>>a[i];
rep(i,1,n){
int l,r;
int x=0;
for(int j=20;j>=0;--j){
if((1ll<<j)&a[i]){
if((1ll<<j)&k){
//aj:1 kj:1 xj:1
l=x+(1<<j);
r=x+(1<<j+1)-1;
pre[l]++;
pre[r+1]--;
//aj:1 kj:1 xj:0
}else{
//aj:1 kj:0 xj:0 :X
//aj:1 kj:0 xj:1
x+=(1ll<<j);
}
}else{
if((1ll<<j)&k){
//aj:0 kj:1 xj:0
l=x;//11010 0 00000
r=x+(1<<j)-1; //10010 0 11111
pre[l]++;
pre[r+1]--;
//aj:0 kj:1 xj:1
x+=(1ll<<j);
}else{
//aj:0 kj:0 xj:0
//aj:0 kj:0 xj:1 :X
}
}
}
pre[x]++;
pre[x+1]--;
}
int mx=0;
mx=pre[0];
for(int i=1;i<=1e7;i++){
pre[i]+=pre[i-1];
mx = max(mx,pre[i]);
}
cout<<mx<<endl;
}
floyd求最短路径的数目模板题
题意:给定一个无向图,求对于每一对起点和终点,每一个点在其中的权值:(在其最短路径的路径数目)/总最短路径数目 之和
思路:设s[u][v]为u到v的最短路径数目
通过floyd一边更新最短路一边更新路径数目
当d[i][j]>d[i][k]+d[k][j]时,s[i][j]=s[i][k]s[k][j]
当d[i][j]=d[i][k]+d[k][j]时,s[i][j]+=s[i][k]s[k][j]
初始化时,注意有边的两个点u,v的s[u][v]=1
int d[150][150];
int s[150][150];
void solve(){
int n,m;cin>>n>>m;
{
memset(d,inf,sizeof d);
rep(i,1,n)d[i][i]=0;
}
rep(i,1,m){
int u,v,w;cin>>u>>v>>w;
d[u][v]=d[v][u]=w;
s[u][v]=s[v][u]=1;
}
rep(k,1,n){
rep(i,1,n){
rep(j,1,n){
if(i==k||j==k)continue;
if(d[i][j]>d[i][k]+d[k][j]){
d[i][j]=d[i][k]+d[k][j];
s[i][j]=s[i][k]*s[k][j];
}else if(d[i][j]==d[i][k]+d[k][j]){
s[i][j]+=(s[i][k]*s[k][j]);
}
}
}
}
rep(k,1,n){
double ans=0;
rep(i,1,n){
rep(j,1,n){
if(i==k||j==k)continue;
if(d[i][k]+d[k][j]==d[i][j]){
ans+=1.0*(s[i][k]*s[k][j])/s[i][j];
}
}
}
cout<<fixed<<setprecision(3)<<(ans)<<endl;
}
}
差分+前缀和trick
题意:给定一个长度为n的数组a,求sum[l,r]=s且max(a[l]....a[r])=k的区间数量
思路:
先求出所有最大值小于等于k的答案数量,再求出所有最大值小于等于k-1的答案数量 ,相减即为答案
和等于s可以通过哈希表+前缀和来解决
奇怪的是这题用gp_hash_table或者unordered_map反而比map要慢
int n,s,x;
void solve(){
cin>>n>>s>>x;
int A=0,B=0;
vector<int>a(n+1);
rep(i,1,n)cin>>a[i];
vector<pii>ax,bx;
int l=-1,r=-1;
rep(i,1,n){
//<=x
if(a[i]>x){
if(l!=-1&&r!=-1){
ax.pb(mp(l,r));
l=-1;r=-1;
}
continue;
}else{
if(l==-1)l=r=i;
else r=i;
}
}
if(l!=-1&&r!=-1){
ax.pb(mp(l,r));
l=-1;r=-1;
}
rep(i,1,n){
//<=x-1
if(a[i]>x-1){
if(l!=-1&&r!=-1){
bx.pb(mp(l,r));
l=-1;r=-1;
}
continue;
}else{
if(l==-1)l=r=i;
else r=i;
}
}
if(l!=-1&&r!=-1){
bx.pb(mp(l,r));
l=-1;r=-1;
}
for(auto[x,y]:ax){
map<int,int>mp;
// gp_hash_table<int,int>mp;
int pre=0;
mp[pre]=1;
rep(i,x,y){
pre+=a[i];
A+=mp[pre-s];
mp[pre]++;
}
}
for(auto[x,y]:bx){
map<int,int>mp;
int pre=0;
mp[pre]=1;
rep(i,x,y){
pre+=a[i];
B+=mp[pre-s];
mp[pre]++;
}
}
cout<<A-B<<endl;
}

浙公网安备 33010602011771号