2019 CCPC wannfly winter camp Day 8

E - Souls-like Game

直接线段树合并矩阵会被卡T掉,因为修改的复杂度比询问的复杂度多一个log,所以我们考虑优化修改。

修改的瓶颈在于打lazy的时候, 所以我们预处理出每个修改矩阵2的幂次,然后直接更新。

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 998244353
#define ld long double
//#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
//#define base 1000000000000000000
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const ull ba=233;
const db eps=1e-9;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N = 200000+10,maxn=4000000+10,inf=0x3f3f3f3f;

int nn, tot;

struct Matrix {
    int a[3][3];
    Matrix() {
        memset(a, 0, sizeof(a));
    }
    void read() {
        for(int i=0;i<3;i++)for(int j=0;j<3;j++)scanf("%d",&a[i][j]);
    }
    void pr()
    {
        for(int i=0;i<3;i++) {
            for(int j=0;j<3;j++)printf("%d ",a[i][j]);
            puts("");
        }
    }
    void init() {
        for(int i = 0; i < 3; i++)
            a[i][i] = 1;
    }
    Matrix operator * (const Matrix &B) const {
        Matrix C;
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                for(int k = 0; k < 3; k++)
                    C.a[i][j] = (C.a[i][j] + 1ll * a[i][k] * B.a[k][j]) % mod;
        return C;
    }
    Matrix operator ^ (int b) {
        Matrix C; C.init();
        Matrix A = (*this);
        while(b) {
            if(b & 1) C = C * A;
            A = A * A; b >>= 1;
        }
        return C;
    }
} o[N<<2], tmp[N][20];
int lazy[N<<2], depth[N<<2], cnt;
bool ok[N<<2];

void pushup(int rt){o[rt]=o[rt<<1]*o[rt<<1|1];}
void pushdown(int l,int r,int rt)
{
    if(!ok[rt]) return;
    int m=(l+r)>>1;
    o[rt<<1]=tmp[lazy[rt]][depth[rt<<1]];
    o[rt<<1|1]=tmp[lazy[rt]][depth[rt<<1|1]];
    lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
    ok[rt<<1] = ok[rt<<1|1] = true;
    ok[rt] = false;
}

void build(int l,int r,int rt,int deep)
{   depth[rt] = deep;
    ok[rt] = false;
    if(l==r){if(l <= nn) o[rt].read();return;}
    int m=(l+r)>>1;
    build(ls, deep-1);build(rs, deep-1);
    pushup(rt);
}

void update(int L,int R,int who,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        o[rt] = tmp[who][depth[rt]];
        lazy[rt] = who;
        ok[rt] = true;
        return;
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,who,ls);
    if(m<R)update(L,R,who,rs);
    pushup(rt);
}
Matrix query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {
        return o[rt];
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    Matrix te;te.init();
    if(L<=m)te=te*query(L,R,ls);
    if(m<R)te=te*query(L,R,rs);
    return te;
}

int main() {
    int n, m, p;
    scanf("%d%d",&n,&m);n--;
    nn = n;
    for(p = 0; (1 << p) < n; p++);
    n = 1 << p;
    build(1, n, 1, p);
    while(m--)
    {
        int op,l,r;scanf("%d%d%d",&op,&l,&r);
        if(op==1) {
            cnt++;
            tmp[cnt][0].read();
            for(int i = 1; i < 20; i++)
                tmp[cnt][i] = tmp[cnt][i - 1] * tmp[cnt][i - 1];
            update(l,r,cnt,1,n,1);
        } else {
            --r;
            Matrix te=query(l,r,1,n,1);
            ll ans=0;
            for(int i=0;i<3;i++)for(int j=0;j<3;j++)add(ans,1ll*te.a[i][j]);
            printf("%lld\n",ans);
        }
    }
    return 0;
}
/*
*/
View Code

 

G - 穗乃果的考试

我们考虑 求和 i * f[ i ]  实际上就是求每个点被多少矩形包括。

那么 求和 i * i * f[ i ] 就是求任意两个点对被多少矩形包括之和, 这个我们可以用树状数组维护。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std;

const int N = 2000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;

struct Bit {
    LL a[N];
    void modify(int x, int val) {
        for(int i = x; i < N; i += i & -i)
            a[i] += val;
    }
    LL sum(int x) {
        LL ans = 0;
        for(int i = x; i; i -= i & -i)
            ans += a[i];
        return ans;
    }
    LL query(int L, int R) {
        if(L > R) return 0;
        return sum(R) - sum(L - 1);
    }
} bit[2];

int n, m;
char s[N][N];

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
        scanf("%s", s[i] + 1);
    LL ans = 0;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            pre = ans;
            if(s[i][j] == '1') {
                ans = (ans + 2 * bit[0].sum(j) * (n-i+1) % mod * (m-j+1) % mod);
                ans = (ans + 2 * bit[1].query(j + 1, m) * j % mod * (n-i+1) % mod);
                bit[0].modify(j, i * j);
                bit[1].modify(j, i * (m-j+1));
                ans = (ans + 1ll * i * j * (n-i+1) % mod * (m-j+1) % mod) % mod;
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}

/*
*/
View Code

 

A - Aqours

我们可以发现一颗子树返回上来的最优节点一定是编号最小的节点。

这题卡dfs, 我按叶子节点的编号顺序把边排序,然后用栈模拟dfs。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std;

const int N = 3e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;

int n, cnt, tot, p[N], mn[N], mnlen[N], bottom[N];
int ans[N];

vector<int> G[N];
vector<int> leaf;

bool cmp(const int& a, const int& b) {
    return mn[a] < mn[b];
}

struct node {
    int who, len, p;
};

inline int read() {
    char ch = getchar(); int x = 0, f = 1;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    } while('0' <= ch && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    } return x * f;
}

int main() {
    n = read();
    if(n == 1) {
        puts("1 -1");
        return 0;
    }
    for(int i = 2; i <= n; i++) {
        p[i] = read();
        G[p[i]].push_back(i);
    }
    for(int i = 1; i <= n; i++)
        mn[i] = inf, mnlen[i] = inf, bottom[i] = inf;
    for(int i = n; i > 1; i--) {
        if(!SZ(G[i])) mn[i] = i, bottom[i] = 0, leaf.push_back(i);
        mn[p[i]] = min(mn[p[i]], mn[i]);
    }
    reverse(leaf.begin(), leaf.end());
    for(int i = 1; i <= n; i++)
        sort(G[i].begin(), G[i].end(), cmp);
    stack<PII> stk;
    stk.push({1, 0});
    while(SZ(stk)) {
        PII u = stk.top(); stk.pop();
        if(!u.se) {
            ans[u.fi] = mnlen[u.fi];
        }
        if(u.se >= SZ(G[u.fi])) {
            bottom[p[u.fi]] = min(bottom[p[u.fi]], bottom[u.fi] + 1);
        } else {
            mnlen[u.fi] = min(mnlen[u.fi], bottom[u.fi]);
            stk.push(mk(u.fi, u.se + 1));
            mnlen[G[u.fi][u.se]] = mnlen[u.fi] + 1;
            stk.push(mk(G[u.fi][u.se], 0));
        }
    }
    for(auto& u : leaf) {
        int val = ans[u];
        printf("%d %d\n", u, val >= inf ? -1 : val);
    }
    return 0;
}

/*
*/
View Code

 

posted @ 2019-01-29 11:40  NotNight  阅读(219)  评论(0编辑  收藏  举报