absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
sgu 119 解题报告
100197 B 解题报告

CF 100735 F 解题报告

absi2011 posted @ Dec 19, 2015 11:00:58 PM in 刷题记录 with tags CF Gym 分块 , 637 阅读

393行,也是够了

题意:感谢@似水流年 的翻译

链接:http://codeforces.com/gym/100735/problem/F

给你一堆椭圆,你要进行这些处理

1,将[l,r]的ai修改为v

2,将[l,r]的bi修改为v

3,将[l,r]的ai加上v

4,将[l,r]的bi加上v

5,求编号[l,r]之间椭圆面积之和/pi(根据椭圆面积公式,S=ai*bi*pi,所以直接是计算ai*bi的和)

6,求[l,r]内有多少个椭圆

***规则:一个椭圆,如果ai<=0或bi<=0那么就会消失,再也不会出现.一个椭圆,如果ai>A或者bi>B,那么它就会被扔进垃圾桶,再也不会出现

下面是absi2011的算法:
分1000块维护这些椭圆,每块100个(为啥不分sqrt(n),理由马上告诉你)
那么每次修改就维护个tag
如果是部分修改就大暴力然后该删删
如果整体修改,有消失的也当部分修改做
因为每个只会消失一次,所以最多消失的复杂度是O(100n),没关系
每次暴力一遍,不考虑消失这种情况,是O(1000)的,似乎也没太大关系,毕竟整体修改常数小..
注意几个问题:
1,标记维护,容易出错
2,对于1或者2操作v非法应该全部处死的时候,不要吝啬时间= =不然会带来很多麻烦
代码:
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[100005];
int b[100005];
const int block_max=1005;
long long sum[block_max];
int suma[block_max];
int sumb[block_max];
int alive[block_max];
int maxa[block_max];
int mina[block_max];
int maxb[block_max];
int minb[block_max];
int taga[block_max];
int tagb[block_max];
int tag_kind_a[block_max];
int tag_kind_b[block_max];
int oper[100005];
int oper_num[100005][3];
int max_a,max_b;
const int block_size=200;
int n;
int block_n;
long long ans=0;
void update(int num)
{
    int i;
    int l=num*block_size;
    int r=(num+1)*block_size;
    sum[num]=0;
    suma[num]=0;
    sumb[num]=0;
    maxa[num]=0;
    maxb[num]=0;
    mina[num]=max_a;
    minb[num]=max_b;
    tag_kind_a[num]=0;
    tag_kind_b[num]=0;
    for (i=l;i<r;i++)
    {
        if (a[i]==-999999999) continue;
        if ((a[i]<=0)||(b[i]<=0)||(a[i]>max_a)||(b[i]>max_b))
        {
            a[i]=-999999999;
            alive[num]--;
            continue;
        }
        suma[num]+=a[i];
        sumb[num]+=b[i];
        maxa[num]=max(maxa[num],a[i]);
        maxb[num]=max(maxb[num],b[i]);
        mina[num]=min(mina[num],a[i]);
        minb[num]=min(minb[num],b[i]);
        sum[num]+=(long long)a[i]*b[i];
    }
}
void break_tag_a(int num)
{
    if (tag_kind_a[num]==0)
    {
        return;
    }
    int l=num*block_size;
    int r=(num+1)*block_size;
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        if (tag_kind_a[num]==1)
        {
            a[i]=taga[num];
        }
        else if (tag_kind_a[num]==2)
        {
            a[i]+=taga[num];
        }
    }
    tag_kind_a[num]=0;
}
void break_tag_b(int num)
{
    if (tag_kind_b[num]==0)
    {
        return;
    }
    int l=num*block_size;
    int r=(num+1)*block_size;
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        if (tag_kind_b[num]==1)
        {
            b[i]=tagb[num];
        }
        else if (tag_kind_b[num]==2)
        {
            b[i]+=tagb[num];
        }
    }
    tag_kind_b[num]=0;
}
void change1_part(int l,int r,int val)
{
    int num=l/block_size;
    break_tag_a(num);
    break_tag_b(num);
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        a[i]=val;
    }
    update(num);
}
void change2_part(int l,int r,int val)
{
    int num=l/block_size;
    break_tag_a(num);
    break_tag_b(num);
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        b[i]=val;
    }
    update(num);
}
void change3_part(int l,int r,int val)
{
    int num=l/block_size;
    break_tag_a(num);
    break_tag_b(num);
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        a[i]+=val;
    }
    update(num);
}
void change4_part(int l,int r,int val)
{
    int num=l/block_size;
    break_tag_a(num);
    break_tag_b(num);
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        b[i]+=val;
    }
    update(num);
}
void query1_part(int l,int r)
{
    int num=l/block_size;
    break_tag_a(num);
    break_tag_b(num);
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        ans+=(long long)a[i]*b[i];
    }
}
void query2_part(int l,int r)
{
    int num=l/block_size;
    break_tag_a(num);
    break_tag_b(num);
    int i;
    for (i=l;i<r;i++)
    {
        if (a[i]<=0) continue;
        ans++;
    }
}
void change1_full(int num,int val)
{
    if (alive[num]==0) return;
    if ((val>max_a)||(val<=0))
    {
        change1_part(num*block_size,(num+1)*block_size,val);
        return;
    }
    suma[num]=alive[num]*val;
    sum[num]=sumb[num]*(long long)val;
    maxa[num]=val;
    mina[num]=val;
    taga[num]=val;
    tag_kind_a[num]=1;
}
void change2_full(int num,int val)
{
    if (alive[num]==0) return;
    if ((val>max_b)||(val<=0))
    {
        change2_part(num*block_size,(num+1)*block_size,val);
        return;
    }
    sumb[num]=alive[num]*val;
    sum[num]=suma[num]*(long long)val;
    maxb[num]=val;
    minb[num]=val;
    tagb[num]=val;
    tag_kind_b[num]=1;
}
void change3_full(int num,int val)
{
    if (alive[num]==0) return;
    if ((maxa[num]+val>max_a)||(mina[num]+val<=0))
    {
        change3_part(num*block_size,(num+1)*block_size,val);
        return;
    }
    suma[num]+=alive[num]*val;
    sum[num]+=sumb[num]*(long long)val;
    maxa[num]+=val;
    mina[num]+=val;
    if (tag_kind_a[num]==0)
    {
        taga[num]=val;
        tag_kind_a[num]=2;
    }
    else
    {
        taga[num]+=val;
    }
}
void change4_full(int num,int val)
{
    if (alive[num]==0) return;
    if ((maxb[num]+val>max_b)||(minb[num]+val<=0))
    {
        change4_part(num*block_size,(num+1)*block_size,val);
        return;
    }
    sumb[num]+=alive[num]*val;
    sum[num]+=suma[num]*(long long)val;
    maxb[num]+=val;
    minb[num]+=val;
    if (tag_kind_b[num]==0)
    {
        tagb[num]=val;
        tag_kind_b[num]=2;
    }
    else
    {
        tagb[num]+=val;
    }
}
void query1_full(int num)
{
    ans+=sum[num];
}
void query2_full(int num)
{
    ans+=alive[num];
}
void full_change(int num,int oper,int val)
{
    if (oper==1)
    {
        change1_full(num,val);
    }
    if (oper==2)
    {
        change2_full(num,val);
    }
    if (oper==3)
    {
        change3_full(num,val);
    }
    if (oper==4)
    {
        change4_full(num,val);
    }
    if (oper==5)
    {
        query1_full(num);
    }
    if (oper==6)
    {
        query2_full(num);
    }
}
void part_change(int num,int l,int r,int oper,int val)
{
    if (oper==1)
    {
        change1_part(l,r,val);
    }
    if (oper==2)
    {
        change2_part(l,r,val);
    }
    if (oper==3)
    {
        change3_part(l,r,val);
    }
    if (oper==4)
    {
        change4_part(l,r,val);
    }
    if (oper==5)
    {
        query1_part(l,r);
    }
    if (oper==6)
    {
        query2_part(l,r);
    }
}
void spilt(int l,int r,int oper,int val)
{
    int i;
    for (i=0;i<block_n;i++)
    {
        int start=i*block_size;
        int end=(i+1)*block_size;
        if ((start>=r)||(end<=l)) continue;
        if ((l<=start)&&(end<=r))
        {
            full_change(i,oper,val);
        }
        else
        {
            part_change(i,max(start,l),min(end,r),oper,val);
        }
    }
    if (oper>4)
    {
        cout<<ans<<'\n';
    }
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int m;
    scanf("%d%d",&n,&m);
    block_n=(n-1)/block_size+1;
    int i;
    for (i=0;i<n;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
    }
    for (i=0;i<m;i++)
    {
        scanf("%d",&oper[i]);
        scanf("%d",&oper_num[i][0]);
        oper_num[i][0]--;
        scanf("%d",&oper_num[i][1]);
        if (oper[i]<=4)
        {
            scanf("%d",&oper_num[i][2]);
        }
    }
    scanf("%d%d",&max_a,&max_b);
    for (i=0;i<block_n;i++)
    {
        alive[i]=block_size;
        update(i);
    }
    ios::sync_with_stdio(false);
    for (i=0;i<m;i++)
    {
        ans=0;
        spilt(oper_num[i][0],oper_num[i][1],oper[i],oper_num[i][2]);
    }
    return 0;
}

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter