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<)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=;while(b){if(b&)ans=ans*a%mod;a=a*a%mod,b>>=;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=;while(b){if(b&)ans=ans*a%c;a=a*a%c,b>>=;}return ans;} using namespace std; const ull ba=;
const db eps=1e-;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N = +,maxn=+,inf=0x3f3f3f3f; int nn, tot; struct Matrix {
int a[][];
Matrix() {
memset(a, , sizeof(a));
}
void read() {
for(int i=;i<;i++)for(int j=;j<;j++)scanf("%d",&a[i][j]);
}
void pr()
{
for(int i=;i<;i++) {
for(int j=;j<;j++)printf("%d ",a[i][j]);
puts("");
}
}
void init() {
for(int i = ; i < ; i++)
a[i][i] = ;
}
Matrix operator * (const Matrix &B) const {
Matrix C;
for(int i = ; i < ; i++)
for(int j = ; j < ; j++)
for(int k = ; k < ; 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 & ) C = C * A;
A = A * A; b >>= ;
}
return C;
}
} o[N<<], tmp[N][];
int lazy[N<<], depth[N<<], cnt;
bool ok[N<<]; void pushup(int rt){o[rt]=o[rt<<]*o[rt<<|];}
void pushdown(int l,int r,int rt)
{
if(!ok[rt]) return;
int m=(l+r)>>;
o[rt<<]=tmp[lazy[rt]][depth[rt<<]];
o[rt<<|]=tmp[lazy[rt]][depth[rt<<|]];
lazy[rt<<]=lazy[rt<<|]=lazy[rt];
ok[rt<<] = ok[rt<<|] = 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)>>;
build(ls, deep-);build(rs, deep-);
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)>>;
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)>>;
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 = ; ( << p) < n; p++);
n = << p;
build(, n, , p);
while(m--)
{
int op,l,r;scanf("%d%d%d",&op,&l,&r);
if(op==) {
cnt++;
tmp[cnt][].read();
for(int i = ; i < ; i++)
tmp[cnt][i] = tmp[cnt][i - ] * tmp[cnt][i - ];
update(l,r,cnt,,n,);
} else {
--r;
Matrix te=query(l,r,,n,);
ll ans=;
for(int i=;i<;i++)for(int j=;j<;j++)add(ans,1ll*te.a[i][j]);
printf("%lld\n",ans);
}
}
return ;
}
/*
*/
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 = + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = ;
const double eps = 1e-; 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 = ;
for(int i = x; i; i -= i & -i)
ans += a[i];
return ans;
}
LL query(int L, int R) {
if(L > R) return ;
return sum(R) - sum(L - );
}
} bit[]; int n, m;
char s[N][N]; int main() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)
scanf("%s", s[i] + );
LL ans = ;
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
pre = ans;
if(s[i][j] == '') {
ans = (ans + * bit[].sum(j) * (n-i+) % mod * (m-j+) % mod);
ans = (ans + * bit[].query(j + , m) * j % mod * (n-i+) % mod);
bit[].modify(j, i * j);
bit[].modify(j, i * (m-j+));
ans = (ans + 1ll * i * j * (n-i+) % mod * (m-j+) % mod) % mod;
}
}
}
printf("%lld\n", ans);
return ;
} /*
*/
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 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = ;
const double eps = 1e-; 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 = , f = ;
while(ch < '' || ch > '') {
if(ch == '-') f = -;
ch = getchar();
} while('' <= ch && ch <= '') {
x = x * + ch - '';
ch = getchar();
} return x * f;
} int main() {
n = read();
if(n == ) {
puts("1 -1");
return ;
}
for(int i = ; i <= n; i++) {
p[i] = read();
G[p[i]].push_back(i);
}
for(int i = ; i <= n; i++)
mn[i] = inf, mnlen[i] = inf, bottom[i] = inf;
for(int i = n; i > ; i--) {
if(!SZ(G[i])) mn[i] = i, bottom[i] = , leaf.push_back(i);
mn[p[i]] = min(mn[p[i]], mn[i]);
}
reverse(leaf.begin(), leaf.end());
for(int i = ; i <= n; i++)
sort(G[i].begin(), G[i].end(), cmp);
stack<PII> stk;
stk.push({, });
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] + );
} else {
mnlen[u.fi] = min(mnlen[u.fi], bottom[u.fi]);
stk.push(mk(u.fi, u.se + ));
mnlen[G[u.fi][u.se]] = mnlen[u.fi] + ;
stk.push(mk(G[u.fi][u.se], ));
}
}
for(auto& u : leaf) {
int val = ans[u];
printf("%d %d\n", u, val >= inf ? - : val);
}
return ;
} /*
*/
2019 CCPC wannfly winter camp Day 8的更多相关文章
- 2019 CCPC wannfly winter camp Day 5
C - Division 思路:我们考虑到一点,从大往小取得顺序是不会有问题的,所以可以直接主席树,但是开不下空间,我们可以log分段求. #include<bits/stdc++.h> ...
- 2020 CCPC Wannafly Winter Camp Day1 C. 染色图
2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...
- CCPC Wannafly Winter Camp Div2 部分题解
Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...
- 2020 CCPC Wannafly Winter Camp Day1 Div.1& F
#include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...
- 2020 CCPC Wannafly Winter Camp Day1 - I. K小数查询(分块)
题目链接:K小数查询 题意:给你一个长度为$n$序列$A$,有$m$个操作,操作分为两种: 输入$x,y,c$,表示对$i\in[x,y] $,令$A_{i}=min(A_{i},c)$ 输入$x,y ...
- 2020 CCPC Wannafly Winter Camp Day2-K-破忒头的匿名信
题目传送门 sol:先通过AC自动机构建字典,用$dp[i]$表示长串前$i$位的最小代价,若有一个单词$s$是长串的前$i$项的后缀,那么可以用$dp[i - len(s)] + val(s)$转移 ...
- 2020 CCPC Wannafly Winter Camp Day1-F-乘法
题目传送门 sol:二分答案$K$,算大于$K$的乘积有多少个.关键在于怎么算这个个数,官方题解上给出的复杂度是$O(nlogn)$,那么计算个数的复杂度是$O(n)$的.感觉写着有点困难,自己写了一 ...
- 2019 wannafly winter camp day 3
2019 wannafly winter camp day 3 J 操作S等价于将S串取反,然后依次遍历取反后的串,每次加入新字符a,当前的串是T,那么这次操作之后的串就是TaT.这是第一次转化. 涉 ...
- 2019 wannafly winter camp
2019 wannafly winter camp Name Rank Solved A B C D E F G H I J K day1 9 5/11 O O O O O day2 5 3/11 O ...
随机推荐
- Problem B: 专家系统 解题报告
Problem B: 专家系统 Description 一个专家系统是指,你雇佣了\(n\)个专家,他们每个人会做出一个结果,然后你从中选取较多的专家的结果组合而成最终的结果.专家系统广泛应用于传统机 ...
- uva11235 FrequentValues (ST表)
既然他是非降的,那我们可以把这个序列每一位转化成到这位位置连续相同的个数,比如001111233444变成121234112123,然后一个区间内的最大值就是众数的位数.但有个问题,就是这个区间的左端 ...
- Go 语言中的方法,接口和嵌入类型
https://studygolang.com/articles/1113 概述 在 Go 语言中,如果一个结构体和一个嵌入字段同时实现了相同的接口会发生什么呢?我们猜一下,可能有两个问题: 编译器会 ...
- 前端学习 -- Css -- 字体分类
在网页中将字体分成5大类: serif(衬线字体) sans-serif(非衬线字体) monospace (等宽字体) cursive (草书字体) fantasy (虚幻字体) 可以将字体设置为这 ...
- python数字转换为字符串的两种方式
主要包括两种形式进行转换: 第一种是str(),将值转换为用户便于阅读的形式: 另一种是repr(),将值转换为合法的python表达式. >>> print repr(" ...
- ideau 2018.1.2安装和使用
此博文的各安装软件.方法技巧仅供研究使用,请勿用于商业活动.下载.操作后请于24小时内删除.对于使用过程中出现的一切问题.责任.纠纷,概不负责. 1.下载ideau-2018.1.2,点击下载,提取码 ...
- Knowledge Tracing -- 基于贝叶斯的学生知识点追踪(BKT)
目前,教育领域通过引入人工智能的技术,使得在线的教学系统成为了智能教学系统(ITS),ITS不同与以往的MOOC形式的课程.ITS能够个性化的为学生制定有效的 学习路径,通过根据学生的答题情况追踪学生 ...
- 百度钱包、百付宝、baifubao接入支付的常见问题
[5004:参数非法,请检查输入参数后重试.]:检查是否缺少了其它必要的参数,我当时是缺少了order_no [5804,抱歉,订单创建失败,请联系客服处理]:即验证签名失败,这个只能参考文档进行处理 ...
- bzoj千题计划241:bzoj3864: Hero meet devil
http://www.lydsy.com/JudgeOnline/problem.php?id=3864 题意: 给你一个DNA序列,求有多少个长度为m的DNA序列和给定序列的LCS为0,1,2... ...
- SQL语句(十二)分组查询
(十二)分组查询 将数据表中的数据按某种条件分成组,按组显示统计信息 查询各班学生的最大年龄.最小年龄.平均年龄和人数 分组 SELECT <字段名表1> FROM <表名> ...