总结,从 766 开始(Div2 30)
Posted rzh123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结,从 766 开始(Div2 30)相关的知识,希望对你有一定的参考价值。
3.10
A
分块
B
分数规划,以前没学过
C
推式子
3.11
A
推结论,先划分连续段,然后从一个长度 >= k 的连续段开始操作
B
推式子
C
平衡树套线段树(为了节省空间需要把内层线段树改成平衡树)
或定期重构+树上差分+动态开点线段树,每个结点上有一棵线段树,每 B 次操作后向上合并
3.12
A
范围小,记忆化搜索,用 map 或 unordered_map 存记忆化的答案
B
C
3.15
A
贪心,可以证明满足条件的情况下越晚休息不会更劣
B
构造,俄罗斯方块,若干次操作后形状不变。不能构造方案消除已有的,应该在已有的基础上构造四整行,需要特判原来为空的情况
C
3.16
A
找规律,可以证明,高精度计算
B
策略是先等待然后用最大速度走
C
dp、背包前后缀和(可删除)
3.17
A
大分类讨论,如果斜箭头有交点就解方程求出,没有说明在四个角,暴力判断,n=2 或 m=2 有特殊情况
B
计算几何,但是卡精度,需要用 int128 实现分数、叉积判断相交
C
类似求凸包的方法
3.18
A
单调栈维护凸包
3.20
A
可持久化线段树,分类讨论
B
期望 dp,推式子
C
多项式
3.21
A
找规律,只有交替操作有效,交替两次相当于向右平移,移出边界的补到左边
B
推结论,线段树维护最大子段和优化
C
3.22
A
推式子,需要计算组合数前缀和
sum C(i,m) (i=0~n) =C(n+1,m+1)
sum C(n,i) (i=0~m) 莫队或分块预处理
B
推式子,选出一些无向边作为不在环上的边并依次定向。
C
网络流,每个点拆开,横纵之间连边,最小割
3.23
A
总状态数不多,可以数位 dp
C
构造
3.24
A
拆开式子,莫队
B
分类讨论+可持久化线段树+二项式定理
C
网络流
3.25
A
结论
B
网络流,但是不是直接建图。先假设所有 o. 都是自己修的,横竖每一个 xo. 的连续段如果满足一定条件就需要把一个替换成别人修的,要求之间有交点可以少替换一个,二分图匹配相交的两个。
C
Div4 思维总结
B题题目中为不能从蓝色中辨别出绿色,可将蓝色也变为绿色,这个点没想到。
D. Line
题意:每个人可选择向左看或者向右看,将看到的人数累加,可一次改变k个人的方向,要加累加值最大。
思路:乍一看感觉很复杂,不知道从哪开始做。但会发现,只有改变方向看到的人数增多,改变才有意义;在修改完一定人数后,会无需继续修改。
1.将改变方向后人数增多的值进行记录,再进行降序排列,统计前缀和,改变数目为cnt。
2.再1~cnt的数目中,累加值为g(初始排列看到的人数)+b[i](前缀和);再cnt+1 ~n的数目中,答案恒为g+b[cnt]
代码:
#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int n,a[N],b[N];
char s[N];
bool cmp(int a,int b) return a>b;
void solve()
cin>>n;
for(int i=0;i<=n;i++) a[i]=b[i]=0;
for(int i=1;i<=n;i++)
cin>>s[i];
int g=0;
for(int i=1;i<=n;i++)
if(s[i]=='L') g+=i-1;
else g+=n-i;
//cout<<g<<endl;
int cnt=0;
for(int i=1;i<=n;i++)
if(s[i]=='L')
if(n-i>i-1) a[++cnt]=n-i-(i-1);
else
if(n-i<i-1) a[++cnt]=i-1-(n-i);
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=n;i++)
b[i]=a[i]+b[i-1];
int p;
for(int i=1;i<=n;i++)
if(i<=cnt)
cout<<g+b[i]<<" ";
else
cout<<g+b[cnt]<<" ";
cout<<endl;
signed main()
//ios;
int T;cin>>T;
while(T--)
solve();
return 0;
E. Counting Rectangles
知识点:矩阵二维前缀和、差分
思路:
1.从高度和宽度的数据范围入手,由于都是1~1000,最高达到1e6次方,可统计n个矩阵中,在i行j列时面积的累加值。
2.由于不能重叠,需要加1和减1的操作,利用差分求出h1~h2和w1 ~w2中的乘积的累加和。
#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
bool cmp1(int a,int b) return a>b;
int n,q,a[1005][1005],b[1005][1005];
void solve()
cin>>n>>q;
for(int i=0;i<1005;i++)
for(int j=0;j<1005;j++)
a[i][j]=b[i][j]=0;
for(int i=1;i<=n;i++)
int x,y;cin>>x>>y;
a[x][y]+=x*y;
for(int i=1;i<=1000;i++)
for(int j=1;j<=1000;j++)
b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j];
while(q--)
int h1,w1,h2,w2;cin>>h1>>w1>>h2>>w2;
h1++,w1++,h2--,w2--;
cout<<b[h2][w2]-b[h1-1][w2]-b[h2][w1-1]+b[h1-1][w1-1]<<endl;
signed main()
//ios;
int T;cin>>T;
while(T--)
solve();
return 0;
F. L-shapes
题意:判断图形"L",每两个之间不能有边和角的重叠。
思路:
1.每个"*"
格子间的8个方向的格子,只能出现三个“ * ”
2.先判断是否能构成图形L,对于判断过的“”进行标记;在判断每个中8个方向的格子是否只有三个*
#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int n,m;
bool vis[105][105];
char a[105][105];
bool check1(int x,int y)
int sum=0;
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
if(a[x+i][y+j]=='*') sum++;
return sum==3;
bool check2(int x,int y)
int sum=1;
vis[x][y]=1;
int flag=0;
if(a[x][y+1]=='*')
vis[x][y+1]=1,sum++;
if(a[x+1][y+1]=='*')
vis[x+1][y+1]=1,sum++;
if(a[x+1][y]=='*')
vis[x+1][y]=1,sum++;
if(a[x+1][y-1]=='*')
vis[x+1][y-1]=1,sum++;
return sum==3;
void solve()
cin>>n>>m;
for(int i=0;i<=n+5;i++)
for(int j=0;j<=m+5;j++)
a[i][j]='0',vis[i][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) cin>>a[i][j];
int g=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]=='*'&&!vis[i][j])
if(check2(i,j)==0)
//cout<<i<<" "<<j<<endl;
g=0;break;
if(a[i][j]=='*')
if(check1(i,j)==0)
g=0;break;
if(g==0) break;
if(g)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
signed main()
//ios;
int T;cin>>T;
while(T--)
solve();
return 0;
G. Even-Odd XOR
题意:下标为奇数的异或值和下标为偶数的异或值相异或结果为0.
思路:看出是构造题,思路就要灵活一点,别老想着去找规律。。。。
1.从题意中需理解到是不是所有元素像疑惑结果为0即可。
2.运用公式b^(a|b)^a==0
,可知前n-2的数可随意放置,第n-1个数为a|b,第n个数为a。
3.需特判若前n-2个数异或结果为0,则最后两个数时同一个值,不满足题意。可取修改第一个元素的值。
#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
bool cmp1(int a,int b) return a>b;
int n,a[N],s;
void solve()
s=0;
cin>>n;
for(int i=0;i<n-2;i++)
a[i]=i;s^=i;
if(s==0)
a[0]=(1<<30)-1;
s=(1<<30)-1;
a[n-2]=s|(1<<30);
a[n-1]=(1<<30);
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
signed main()
//ios;
int T;cin>>T;
while(T--)
solve();
return 0;
以上是关于总结,从 766 开始(Div2 30)的主要内容,如果未能解决你的问题,请参考以下文章
CF R630 div2 1332 E Height All the Same
前行◇第3站◇ Codeforces Round #512 Div2