题目描述
众所周知,9406计算机大佬众多,他们不仅代码能力强,而且都精通物理。物理无处不在,甚至坐电梯的时候,zck和xxr都在讨论若电梯突然失重会怎样。身为文科生的华华和奕奕非常难过,他们决定学习物理,不能让小伙伴们看不起。奕奕现在正在研究一道物理题。
有Q次操作:
若op<mark>1,输入v,t,m,表示在t时刻从无穷高处以初速度v垂直向下抛出一个质量为m的小球。
若op</mark>2,输入v,t。表示询问t时刻所有速度小于等于v的小球的动能之和是多少。
一个速度为v,质量为m的物体的动能等于0.5mvv,为了防止精度误差,设原来的答案是ans,则你只需输出2ans%(1e9+7)即可。

输入描述:
输入Q。 接下来Q行。
先输入op,若op<mark>1,输入v,t,m。
若op</mark>2,输入v,t表示一次询问。
1<=Q,t,m<=3e5。
若op<mark>1,1<=v<=3e5。
若op</mark>2,1<=v<=4e6。
t是不严格递增的,即t[1]<=t[2]<=t[3]<=…<=t[Q]
重力加速度取g=10m/s^2

输出描述:
对于每次询问输出2*ans%(1e9+7)

示例1
输入
复制

7
1 1 1 2
2 1 2
2 11 2
1 3 2 5
1 1 4 3
2 20 4
2 30 4

输出
复制

0
242
3
2648


如果我们不做改变,很难判断有哪些速度是小于当前询问的速度的。

于是我们想到,我们定一个标准。全部都看成从 t = 0 时开始丢下的小球,那么我们就很好判断了,直接树状数组维护一下即可。

那我们怎么计算答案呢?我们可以看一下公式: m * (v0 + g * t) ^2 ,不难化简,我们维护三个变量即可,因为起点已经确定了,所以最后把t带入计算答案即可。


AC代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int p=1e9+7;
const int N=8e6+10,base=4e6;
int q,d[N][3];
inline void add(int x,int v,int k){for(;x<=base*2;x+=(x&(-x)))   d[x][k]+=v;}
inline int ask(int x,int k){int s=0; for(;x;x-=(x&(-x))) s+=d[x][k]; return s;}
signed main(){
    cin>>q;
    while(q--){
        static int op,v,t,m;    scanf("%lld %lld %lld",&op,&v,&t);
        if(op==1){
            scanf("%lld",&m); v-=10*t;
            add(v+base,m*v%p*v%p,0); 
            add(v+base,100*m,1); 
            add(v+base,(20*v*m%p+p)%p,2);
        }else{
            v-=10*t; static int res=0;
            res=ask(v+base,0);
            res=(res+ask(v+base,1)*t%p*t%p)%p;
            res=(res+ask(v+base,2)*t%p)%p;
            printf("%lld\n",res);
        }
    }
    return 0;
}