20220324
A.Reverse
找到首个不在自己位置的数翻转一下就可以了
// Problem: A. Reverse
// Contest: Codeforces - Codeforces Round #771 (Div. 2)
// URL: https://codeforces.com/contest/1638/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
int p[550];
int a[550];
void so1ve(){
mem(a,0);
mem(p,0);
int n;cin>>n;
forr(i,1,n) {
cin>>a[i];
p[a[i]] = i;
}
forr(i,1,n){
if(p[i] == i) continue;
else{
reverse(a+i,a+1+p[i]);
break;
}
}
forr(i,1,n) cout << a[i] <<" \n"[i==n];
}
B. Odd Swap Sort
只有当相邻两项为一个奇数与一个偶数才能交换位置,那么会发现奇/偶数之间的相对顺序不会改变,只需要判断奇数和偶数初始序列是否有序即可
bool judge(vector<int> s){
int len = s.size();
for(int i = 0; i < len-1;i++){
if(s[i] > s[i+1]) return false;
}
return true;
}
void so1ve(){
int n;cin>>n;
vector<int> a,b;
forr(i,1,n){
int x;cin>>x;
if(x&1) a.push_back(x);
else b.push_back(x);
}
if(judge(a) && judge(b)) puts("Yes");
else puts("No");
}
C. Inversion Graph
单调栈
可以用栈来维护每个连通块最大的值,答案为最后栈的元素个数
int stk[100005];
int tt;
void so1ve(){
tt = 0;
int n;cin>>n;
vector<int> a(n+1);
forr(i,1,n) cin>>a[i];
stk[++tt] = a[1];
forr(i,2,n){
int t = a[i];
while(tt && stk[tt] > a[i]){
t = max(t,stk[tt]);
tt--;
}
stk[++tt] = t;
}
cout << tt << endl;
}
D. Big Brush
bfs
找到最后一次刷上的数一定是四个相同一样的,标记为特殊的方块表示可以和其他任何颜色匹配,后用特殊的方块和周围的颜色进行匹配,若存在四个方块相同的
(
i
,
j
)
(i,j)
(i,j)放入队列中,结束后判断是否所有方块均变为特殊方块。
void so1ve(){
int n,m;cin>>n>>m;
vector<vector<int>> a(n+1);
forr(i,1,n){
a[i].resize(m+1);
forr(j,1,m) cin>>a[i][j];
}
auto find = [&](int x,int y){
int col = 0;
if(x<=0||x>=n||y<=0||y>=m) return make_pair(false,col);
set<int> s;
for(auto it:{a[x][y],a[x+1][y],a[x][y+1],a[x+1][y+1]}){
if(it != -1) s.insert(it),col = it;
}
return make_pair(s.size()==1,col);
};
auto paint = [&](int x,int y){
a[x][y] = a[x+1][y] = a[x][y+1] = a[x+1][y+1] = -1;
};
vector<tuple<int,int,int>> ans;
queue<tuple<int,int,int>> q;
forr(i,1,n-1)forr(j,1,m-1){
auto [res, col] = find(i,j);
if(res){
q.push({i,j,col});
ans.push_back({i,j,col});
paint(i,j);
}
}
while(!q.empty()){
auto [x,y,col] = q.front();
q.pop();
for(int i = x-1;i <= x+1;i++)
for(int j = y-1;j <= y+1;j++){
auto [res,col] = find(i,j);
if(res){
q.push({i,j,col});
ans.push_back({i,j,col});
paint(i,j);
}
}
}
forr(i,1,n)forr(j,1,m){
if(a[i][j] != -1) {
puts("-1");
return;
}
}
reverse(ans.begin(),ans.end());
cout << ans.size() << endl;
for(auto [x,y,z]:ans){
cout << x <<" " << y <<" "<< z << '\n';
}
}
E. Colorful Operations
线段树
3
3
3个操作,每个元素有价值和颜色两个属性
1.将
[
L
,
R
]
[L,R]
[L,R]的颜色变为
c
c
c
2.将颜色
c
c
c 的值增加
x
x
x
3.输出
a
i
a_i
ai 的值
通过延迟标记
l
a
z
y
[
]
lazy[]
lazy[] 数组来计算一个元素增加价值
线段树里用
l
z
lz
lz 变量来维护其值的变化
查询
a
i
a_i
ai 时为
a
s
k
(
1
,
i
)
+
l
a
z
y
[
c
o
l
[
i
]
]
ask(1,i) + lazy[col[i]]
ask(1,i)+lazy[col[i]];
对于操作1,利用区间修改来对颜色进行修改
这里
l
z
lz
lz 标记的变化为
t[u].lz += lazy[t[u].col];
t[u].col = c;
t[u].lz -= lazy[t[u].col];
因为如果当前 i i i 的颜色为 c 1 c_1 c1 ,要变为颜色 c 2 c_2 c2 ,因为若颜色不发生改变查询时会加上通过 2 2 2操作 c 1 c_1 c1 增加的量,但是现在颜色已经改变为 c 2 c_2 c2 最后查询的时候就会去加上 c 2 c_2 c2 的增量,所以 l z lz lz要先加上 l a z y [ c 1 ] lazy[c_1] lazy[c1] ,此增量已经对i有影响,同时要前去变为 c 2 c_2 c2之前已经对颜色 c 2 c_2 c2的值造成影响的 l a z y lazy lazy,不减去的话最后查询时会使i 还未变成 c 2 c_2 c2 前对 c 2 c_2 c2的增量加到 i i i 的值
code
int n,m;
struct tree{
int l,r;
int col;
int lz;
bool sam; // 为护两个子区间的颜色是否相同
}t[N<<2];
int lazy[1000005];
void up(int i){
// 儿子颜色要相同且儿子的儿子也要颜色相同才能传值
if(t[(i<<1)].sam && t[(i<<1|1)].sam && t[(i<<1)].col == t[(i<<1|1)].col){
t[i].col = t[i<<1].col;
t[i].sam = true;
}
否则就是儿子不相同
else t[i].sam = false;
}
void down(int i){
if(!t[i].sam) return;
t[i<<1].lz += t[i].lz;
t[i<<1|1].lz += t[i].lz;
t[i<<1].col = t[i].col;
t[i<<1|1].col = t[i].col;
t[i].lz = 0;
}
void build(int i, int l, int r) {
t[i].l = l, t[i].r = r;
t[i].sam = true, t[i].col = 1;
t[i].lz = 0;
if (l == r)
return;
int mid = (l + r) >> 1;
build(i << 1, l, mid), build(i << 1 | 1, mid + 1, r);
up(i);
}
void change(int u,int l,int r,int c){
if (t[u].l > r || t[u].r < l)
return;
// 当前区间的儿子要颜色相同才能改值,是因为不同颜色的lz变化不同
if (t[u].l >= l && t[u].r <= r && t[u].sam) {
t[u].lz += lazy[t[u].col];
t[u].col = c;
t[u].lz -= lazy[t[u].col];
return;
}//延迟修改了每个数的值,只有当这个数的颜色发生变化时,才修改这个数的值
int mid = (l + r) >> 1;
down(u);
change(u << 1, l, r, c), change(u << 1 | 1, l, r, c);
up(u);
}
int ask(int u, int x) {
if (t[u].l == x && t[u].r == x)
return t[u].lz + lazy[t[u].col];
down(u);
int mid = t[u].l + t[u].r >> 1;
if (x <= mid)
return ask(u << 1, x);
else
return ask(u << 1 | 1, x);
}
string s;
int l,r,col;
int val;
int x;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
build(1,1,n);
while(m--){
cin>>s;
if(s == "Color"){
cin>>l>>r>>col;
change(1,l,r,col);
}
else if(s == "Add"){
cin>>col>>val;
lazy[col] += val;
}else{
cin>>x;
cout << (ask(1,x)) << endl;
}
}
return 0;
}