等差数列求和,算出多少个整周期。
二分或解方程
#include <cstdio>
#include <iostream>
#include <cmath>
#define ll unsigned long long
using namespace std;
ll n,t;
bool check(ll a,ll d1,ll mid)
{
ll c=2;
ll ans=a*mid+(((mid-1)*mid)/c)*d1;
return ans<=t;
}
int main()
{
freopen("sample.in","r",stdin);
//freopen("sample.out","w",stdout);
ll anse=0;
scanf("%lld%lld",&n,&t);
for(int i=1;i<=n;i++)
{
ll x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
if(x==0)
{
anse+=t;
continue;
}
/*if(y==0&&z==0)
{
continue;
}*/
ll l=0,r=t/x+y+1,ans=0;
while(l<=r)
{
ll mid=(l+r)/2;
if(check(x+y,z,mid)) l=mid+1,ans=mid;
else r=mid-1;
}
ll c=2;
ll ansx=(x+y)*ans+(((ans-1)*ans)/c)*z;
if(ansx==t)
anse+=y*ans+((ans-1)*(ans)/c)*z;
else
{
anse+=y*ans+((ans-1)*(ans)/c)*z;
if(t-ansx>x) anse+=(t-ansx-x);
//printf("%lld\n",xxxx);
//printf("%lld\n",ansy);
}
//printf("%lld\n",ansx);
}
printf("%lld",anse);
return 0;
}
暴力模拟
定义pushup x 数组为所以操作点对x答案的贡献
size[x]为x有多少儿子
son[x]表示x的子节点操作了几次
tag[x]表示x操作了几次
操作x,pushup[x]很明显要+size[x]+1
对于pushup[fat[x]]+=2(当前点+父亲点)
对pushup[fat[fat[x]]]++(x 的父节点)
tag[x]++
son[fat[x]]++
这次操作x对答案的贡献即为
1:pushup[x](本身影响 的点)
2:tag[fat[x]]*2(父节点的贡献)
3:tag[fat[fat[x]]](父节点的父节点的贡献)
4:temp+=son[fa[x]]-tagx
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
int n, m;
int fa[100010];
ll ans,tag[100010],pushup[100010],son[100010],size[100010];
ll read()
{
ll res = 0;
char ch = 0;
while (ch < '0' || ch > '9')
ch = getchar();
while (ch >= '0' && ch <= '9')
{
res = res * 10 + ch - '0';
ch = getchar();
}
return res;
}
int main()
{
n=read();
m=read();
for (int i=2;i<=n;i++)
{
fa[i]=read();
size[i]++;
size[fa[i]]++;
}
while (m--)
{
ll x;
x=read();
pushup[x] += size[x] + 1;
pushup[fa[x]] += 2;
pushup[fa[fa[x]]]++;
tag[x]++;
son[fa[x]]++;
long long temp = pushup[x];
temp+=tag[fa[x]]*2;
temp+=tag[fa[fa[x]]];
temp+=son[fa[x]]-tag[x];
ans+=temp;
}
printf("%lld\n", ans);
return 0;
}