重心拉格朗日插值模板题。
用上面那篇文章的公式计算。插入时更新每个 (w_i),询问时分别 (O(n)) 计算 (l(k)) 和 (sumlimits_{i=1}^n frac{w_i}{k-x_i}) 即可。注意使用上述公式时 (k-x_i) 不能为 (0),所以我们要特判 (k=x_i) 的情况。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define int long long
using namespace std;
const int N=3009,M=998244353;
int n,cnt,x[N],y[N],w[N];
void init()
{
scanf("%lld",&n);
}
int ksm(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=res*a%M;
b>>=1,a=a*a%M;
}
return res;
}
void work()
{
int opt,X,Y;
while(n--)
{
scanf("%lld",&opt);
if(opt==1)
{
scanf("%lld %lld",&X,&Y);
x[++cnt]=X,y[cnt]=w[cnt]=Y;
for (int i=1;i<cnt;i++)
w[i]=w[i]*ksm(x[i]-x[cnt],M-2)%M,
w[cnt]=w[cnt]*ksm(x[cnt]-x[i],M-2)%M;
}
else
{
scanf("%lld",&X);
int flag=0;
for (int i=1;i<=cnt;i++)
if(X==x[i])
{
flag=1,printf("%lld
",y[i]);
break;
}
if(flag) continue;
int tmp=1,_tmp=0;
for (int i=1;i<=cnt;i++)
tmp=tmp*(X-x[i])%M;
for (int i=1;i<=cnt;i++)
_tmp=(_tmp+w[i]*ksm(X-x[i],M-2)%M)%M;
printf("%lld
",(tmp*_tmp%M+M)%M);
}
}
}
signed main()
{
init();
work();
return 0;
}