zoukankan      html  css  js  c++  java
  • BZOJ2752: [HAOI2012]高速公路(road)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2752

    首先以点代边,设第i个点表示i-1>i。

    对于每个点算贡献,假设这个点是p,当前询问区间是[l,r],那么它的贡献为2*(p-l)*(r-p+1)*vp/((r-l)*(r-l+1)),打开合并同类项得到-(l+l*r)*vp+(l+r+1)*p*vp-p^2*vp

    那么我们只要快速处理出区间的vp,p*vp,p^2*vp然后就可以用线段树维护了。

    1^2+2^2+……+n^2=n*(n+1)*(2*n+1)/6

    (写代码半个小时,打错一行代码调一晚上,真是太弱了TAT。。。由于我懒得不行于是所有变量都开LL,好像也不会特别慢嘛TAT

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxn 100500
    using namespace std;
    typedef long long ll;
    struct data{ll s[4],tag,size,l,r;
    }t[maxn*5];
    ll n,m;
    ll ans,s;
    ll read(){
        ll x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {
            if (ch=='-') f=-1; ch=getchar();
        }
        while (isdigit(ch)){
            x=x*10+ch-'0'; ch=getchar();
        }
        return x*f;
    }
    ll gcd(ll x,ll y){
        if (y==0) return x;
        return gcd(y,x%y);
    }
    void print(ll ans,ll s){
        ll k=gcd(ans,s);
        printf("%lld/%lld
    ",ans/k,s/k);
    }
    void build(ll i,ll l,ll r){
        t[i].l=l; t[i].r=r; t[i].tag=0; t[i].size=(r-l+1);
        if (l==r) return ;
        ll mid=(l+r)/2;
        build(i*2,l,mid); build(i*2+1,mid+1,r);
    }
    ll get(ll n){
        return n*(n+1)*(2*n+1)/6;
    }
    void update(ll i,ll z){
        t[i].tag+=z;
        t[i].s[1]+=t[i].size*z;
        t[i].s[2]+=t[i].size*(t[i].l+t[i].r)/2*z;
        t[i].s[3]+=(get(t[i].r)-get(t[i].l-1))*z; 
    }
    void up(ll i){
        rep(j,1,3) t[i].s[j]=t[i*2].s[j]+t[i*2+1].s[j];
    }
    void Down(ll i){
        update(i*2,t[i].tag); update(i*2+1,t[i].tag);
        t[i].tag=0;
    }
    void add(ll i,ll x,ll y,ll z){
        ll l=t[i].l,r=t[i].r,mid=(l+r)/2;
        if (l==x&&r==y) {
            update(i,z); return;
        }
        if (t[i].tag) Down(i);
        if (x<=mid) add(i*2,x,min(mid,y),z);
        if (y>=mid+1) add(i*2+1,max(x,mid+1),y,z);
        up(i);
    }
    ll ask(ll i,ll x,ll y,ll k){
        ll l=t[i].l,r=t[i].r,mid=(l+r)/2;
        ll ans=0;
        if (l==x&&y==r) return t[i].s[k];
        if (t[i].tag) Down(i);
        if (x<=mid) ans+=ask(i*2,x,min(mid,y),k);
        if (y>=mid+1) ans+=ask(i*2+1,max(x,mid+1),y,k);
        return ans;
    }
    int main(){
        n=read(); m=read();
        build(1,1,n);
        rep(i,1,m){
            ll x,y,l,r; ll z;
            char ch=getchar(); while (ch!='C'&&ch!='Q') ch=getchar();
            if (ch=='C'){
                x=read(); y=read(); scanf("%lld",&z);
                add(1,x+1,y,z);
            }
            else {
                l=read(); r=read();
                ans=(-(l+l*r)*ask(1,l+1,r,1)+(l+r+1)*ask(1,l+1,r,2)-ask(1,l+1,r,3));
                s=(r-l)*(r-l+1)/2;
                print(ans,s);
            }
        }
        return 0;
    }
  • 相关阅读:
    多点触控版的驱动安装
    模板类的继承
    c++大整数运算
    RHEL6单用户模式切换
    Dlna相关开源项目收集整理
    给我的当前RHEL6新增一块硬盘!
    交叉编译libconv
    OSCam学习记录
    Android中的应用!!!!
    Elf文件格式学习笔记
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5001863.html
Copyright © 2011-2022 走看看