王者场ABC题解
反思一下:简单题没想好就急着敲,浪费时间,难的题反而做的快,因为想好了后代码是不会出问题的。
所以还是要先想清楚过程确定没问题在敲代码,主要是想的时间。
- A:奇怪的排序问题
想清楚每次操作的过程就好做了:
肯定是从高往低去处理,(因为无论你怎么动矮的,都不会让高的人往后走)
对于当前最高的人x,如果他不是最后面的一个,则需要花费1次把他移动到最后排。(且他原本的位置置为空)
如果他是当前最后排,则不需要移动。
处理过程注意维护空的位置即可。
const int M = 1e6 + 10;
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @param a int整型vector
* @return int整型
*/
int wwork(int n, vector<int>& v) {
// write code here
int r=n-1;
int mp[1000007]={0};
for(int i=0;i<n;i++){
mp[v[i]-1]=i;
}
int nm=0;
for(int i=n-1;i>=0;i--){
while(r>=0 && v[r]==-1)r--;
// cout<<i<<" "<<mp[i]<<" "<<r<<" "<<nm<<endl;
if(mp[i]!=r)nm++,v[mp[i]]=-1;
else{
r--;
}
}
return nm;
}
};- B:XOR和
两种方法:
方法一:打表找规律(推荐这种,尤其是表很快就能打出来的题,能省去很多时间)
打表发现:
对于一个数x,其初始f[x]=0;
如果一个数x是1的倍数,则f[x]+=1,
如果一个数x是2的的倍数,则f[x]+=2;
如果一个数x是4的的倍数,则f[x]+=4;
如果一个数x是8的的倍数,则f[x]+=8;
…………
然后直接枚举2的次幂即可。
方法二:数学推导
设一个数n,其最低位的1在y上。
则n-1 ^ n = ((1<<y) -1 ); (因为高于y的位n和n-1都不变,低于y的位刚好是n为0,n-1为1)
比如一个数 (二进制表示)
10100
其减一为:
10011
则10100^10011 = 11 = 3
然后就转化为方法一中的规律去枚举求解即可
typedef long long ll;
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @return long长整型
*/
long long Sum(int n) {
// write code here
ll sm=(1+n)*n/2;
ll ans=0,nw=0;
for(int i=0;i<31;i++){
ll tp=1ll<<i;
nw=tp;
ans+=nw*(n/tp);
}
return ans;
}
};- C:牛牛的路径和
枚举每一位,分开进行算贡献。
只考虑第i位,树上点权就只有0/1两种,我们求的是每个全1连通块内,路径个数nm,然后让nm*(1<<x)就是这个连通块的点在第i位上对答案的贡献了。
枚举所有位即可算出最终答案。
const int M = 1e5+7;
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型 点的个数
* @param u int整型vector 每条边的起点
* @param v int整型vector 每条边的终点
* @param p int整型vector 每个点的价值
* @return long长整型
*/
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
int a[M],vs[M];
long long nm;
void dfs(int x){
vs[x]=1;
nm++;
for(int i=head[x];i;i=ee[i].nxt){
int y=ee[i].to;
if(vs[y]||a[y]==0)continue;
dfs(y);
}
}
long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& p) {
// write code here
init(n);
for(int i=0;i<n-1;i++){
a[i]=p[i];
add(u[i],v[i],1);
add(v[i],u[i],1);
}
long long ans=0;
for(int sta=0;sta<=20;sta++){
for(int i=0;i<n;i++)if((p[i]>>sta)&1)a[i]=1;else a[i]=0;
memset(vs,0,sizeof(vs));
for(int i=0;i<n;i++){
if(vs[i]||a[i]==0)continue;
nm=0;
dfs(i);
ans+=(nm+nm*(nm-1)/2)*(1<<sta);
}
}
return ans;
}
};

京公网安备 11010502036488号