iwtgm-6
A.
感觉1和2非常神奇,可以得到非常神奇的结论,
自我猜想可能是因为首先它们的值很小,那么可以表示的范围非常大,
然后可以改变奇偶性,范围就更大了
这题的结论就是连续1的个数/3
先特判第一步是1一定有一个贡献
然后加上后面连续1的个数/3
void solve()
{
int n,ans;cin>>n>>ans;
int cnt=0;
for(int i=1,a;i<n;i++){
cin>>a;
if(a==1)++cnt;
else{
ans+=cnt/3;
cnt=0;
}
}
cout<<ans+cnt/3<<endl;
}
B.
把数组离散化,只对端点进行处理,
头端点的值为1,尾端点的值为-1,尾端点的位置要+1,(因为也算在覆盖范围内)把所有端点打乱按位置排序
一个变量cnt记录当前覆盖的线段个数,tmp记录的是上一个端点的位置
两个端点的差是cnt的贡献
int n;
ll l,r,ans[N],cnt,tmp;
map<ll,ll>m;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>l>>r;
m[l]++;m[++r]--;
}
for(auto tt:m){
ans[cnt]+=tt.first-tmp;
tmp=tt.first;
cnt+=tt.second;
}
for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
}
C.
树上差分,
前缀和就是当前节点的答案,
特定深度的节点很多,但我们dfs是在一个子树内进行的,到回溯的时候把差分数组归位(影响消去)就不会对其他子树产生影响
#define pii pair<ll,ll>
ll n,q,dep[N],val[N],ans[N];//深度数组,差分数组,答案数组
vector<int>g[N];//树
vector<pii>vec[N];//操作
void dfs(ll u,ll pre,ll sum){
sum+=val[dep[u]];//差分数组求前缀和就是原数组,这里就是单个点的值
for(int i=0;i<vec[u].size();i++){//把影响算入
sum+=vec[u][i].second;
if(dep[u]+vec[u][i].first+1<=n)val[dep[u]+vec[u][i].first+1]-=vec[u][i].second;//差分
}
ans[u]=sum;//可以有答案了,因为影响是对子树的影响,现在该节点已经是根了,别人无法再对它产生影响
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(v==pre)continue;
dep[v]=dep[u]+1;//深度
dfs(v,u,sum);
}
for(int i=0;i<vec[u].size();i++){
if(dep[u]+vec[u][i].first+1<=n)val[dep[u]+vec[u][i].first+1]+=vec[u][i].second;//消除影响,不影响其他子树
}
}
void solve()
{
cin>>n;
for(int i=1,x,y;i<n;i++){
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
cin>>q;
for(int i=1,x,y,z;i<=q;i++){
cin>>x>>y>>z;
vec[x].push_back({y,z});
}
dep[1]=1;
dfs(1,0,0);
for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
}