JZOJ5439. 【NOIP2017提高A组集训10.31】Calculate 乱搞

来源:互联网 发布:深圳水务集团网络投诉 编辑:程序博客网 时间:2024/06/16 18:54

这里写图片描述
严格来说这题确实就是乱搞。。
明显来说,有式子都要你化掉。
这题也是一样的,设一个数x,假如有Ac1,Ac2....Ack=x
那么原来的式子就变成了这里写图片描述
那么我们考虑设g[i]=b[i]%x,即按照a[i]来分组,在设在k个数中有t个数的g要大于T%x.
那么有:这里写图片描述
然后预处理出后面那两个东西就可以了。

#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long ll;const int N=1e6+5;int n,m;ll a[N],b[N];const int inf=1e9; ll t[N],sum[605][605];inline ll read(){    ll x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline ll pd(ll T){    ll ans=0;    fo(i,1,500)    {        ans=ans+1ll*(T/i)*sum[i][i];        ans=ans-(sum[i][i]-sum[i][T%i])-t[i];    }    return ans;}int main(){    freopen("calculate.in","r",stdin);    freopen("calculate.out","w",stdout);    int cas;    scanf("%d",&cas);    while (cas--)    {        scanf("%lld%lld",&n,&m);        memset(t,0,sizeof(t));        memset(sum,0,sizeof(sum));        fo(i,1,n)a[i]=read();        fo(i,1,n)b[i]=read();        fo(i,1,n)        {            t[a[i]]+=1ll*b[i]/a[i];            sum[a[i]][b[i]%a[i]]++;        }        fo(i,1,501)        fo(j,1,i)sum[i][j]+=sum[i][j-1];        while (m--)        {            int op,x,y;             op=read();            if(op<=2)            {                x=read(),y=read();                if (op==1)                {                    t[a[x]]-=1ll*b[x]/a[x];                    fo(i,b[x]%a[x],a[x])                    sum[a[x]][i]--;                    t[y]+=1ll*b[x]/y;                    fo(i,b[x]%y,y)                    sum[y][i]++;                    a[x]=y;                }                else if (op==2)                {                    t[a[x]]+=1ll*y/a[x]-b[x]/a[x];                    int l=b[x]%a[x],r=y%a[x],v=-1;                    if (l>r)swap(l,r),v=1;                    fo(i,l,r-1)sum[a[x]][i]+=v;                    b[x]=y;                }            }            else            {                ll k=read();                ll l=0,r=1e13;                while (l<=r)                {                    ll mid=(l+r)/2;                    if (pd(mid)>=k)r=mid-1;                    else l=mid+1;                }                printf("%lld\n",r+1);            }        }    } }