《洛谷P2930 [USACO09HOL]Holiday Painting G》

一开始没注意数据范围~

可以发现列最大只有15。

并且我们修改的是一个矩形。

那么就是一列列修改并且统计答案。

这里就可以用线段树,对每列建树,然后更新统计答案。

具体怎么统计,就是因为每次都是将一个区间内的数改成1或0,那么我们先统计出每个区间的标准1和0个数。

那么改成哪个就是哪个为相同的答案。

然后注意一些细节就行了

《洛谷P2930 [USACO09HOL]Holiday Painting G》
// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 5e4+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){/*freopen("data1.in","r",stdin);
freopen("data1.out","w",stdout);*/}

int n,m,q;
string a[N];
struct Node{int L,r,sum1,sum0,val,tag;}node[20][N<<2];
void Pushup(int id,int idx)
{
    node[id][idx].val = node[id][idx<<1].val + node[id][idx<<1|1].val;
}
void Pushdown(int id,int idx)
{
    if(node[id][idx].tag != -1)
    {
        int tag = node[id][idx].tag;
        if(tag == 0)
        {
            node[id][idx<<1].val = node[id][idx<<1].sum0;
            node[id][idx<<1|1].val = node[id][idx<<1|1].sum0;
        }
        else
        {
            node[id][idx<<1].val = node[id][idx<<1].sum1;
            node[id][idx<<1|1].val = node[id][idx<<1|1].sum1;
        }
        node[id][idx<<1].tag = node[id][idx<<1|1].tag = tag;
        node[id][idx].tag = -1;
    }
}
void build(int L,int r,int id,int idx)
{
    node[id][idx].L = L,node[id][idx].r = r;
    node[id][idx].tag = -1;
    if(L == r)
    {
        if(a[L-1][id-1] == '0') node[id][idx].sum0++,node[id][idx].val = 1;
        else node[id][idx].sum1++;
        return ;
    }      
    int mid = (L+r)>>1;
    build(L,mid,id,idx<<1);
    build(mid+1,r,id,idx<<1|1);
    node[id][idx].sum0 = node[id][idx<<1].sum0 + node[id][idx<<1|1].sum0;//上限
    node[id][idx].sum1 = node[id][idx<<1].sum1 + node[id][idx<<1|1].sum1;
    Pushup(id,idx);
}
void update(int L,int r,int id,int idx,int val)
{
    if(node[id][idx].L >= L && node[id][idx].r <= r)
    {
        if(val == 0) node[id][idx].val = node[id][idx].sum0;
        else node[id][idx].val = node[id][idx].sum1;
        node[id][idx].tag = val;
        return ;
    }
    int mid = (node[id][idx].L + node[id][idx].r)>>1;
    Pushdown(id,idx);
    if(mid >= L) update(L,r,id,idx<<1,val);
    if(mid < r) update(L,r,id,idx<<1|1,val);
    Pushup(id,idx);
}
int main()
{
    IO;CT0;
    cin >> n >> m >> q;
    for(rg int i = 0;i < n;++i) cin >> a[i];
    for(rg int j = 0;j < m;++j) build(1,n,j+1,1);
    while(q--)
    {
        int r1,r2,c1,c2,z;
        cin >> r1 >> r2 >> c1 >> c2 >> z;
        for(rg int i = c1;i <= c2;++i) update(r1,r2,i,1,z);
        int ans = 0;
        for(rg int i = 1;i <= m;++i) ans += node[i][1].val;
        cout << ans << endl;
    }
    system("pause");    
}
View Code

 

上一篇:tile painting


下一篇:C. Cave Painting(最小公倍数的应用)