C
- 題意: 有兩種管子(直和彎的),給出一個由這兩種管子構成的$n*2$的矩陣,問能不能經過任意調整管子的朝向使得左上角能走到右下角.
- 思路: 直管只能直着走,彎管必須上下都是彎管才能向前走,且要走到另一層.
#include<bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<int,int> pii;
const int N = 2e5+10;
int op[N][2];
int n;
string s;
int main(){
// freopen("1.out","w",stdout);
int t,val;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
cin >> s;
for(int i=0;i<n;++i){
if(s[i]=='1' || s[i]=='2') op[i+1][0] = 1;
else op[i+1][0] = 2;
}
cin >> s;
for(int i=0;i<n;++i){
if(s[i]=='1' || s[i]=='2') op[i+1][1] = 1;
else op[i+1][1] = 2;
}
int step = n*3;
int x = 1, y = 0,px =0;
while(step--){
if(x == n+1) break;
if(op[x][y]==1) x++;
else{
if(op[x][1-y]!=2) break;
x++; y = 1-y;
}
}
if(x==n+1 && y==1){
puts("YES");
}else{
puts("NO");
}
}
return 0;
}
D
- 題意: 給出一個字符串,操做有修改某個點和查詢區間內有多少不一樣的字母.
- 思路: 維護$26$個樹狀數組,表明每一個字母從$1到i$出現了多少次,對於查詢,遍歷這$26$個樹狀數組看每一個字母是否在區間內出現,對於修改,這個位置原來的字母減去1,新來的字母加上1便可.
#include <iostream>
#include <stdio.h>
#include <map>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n ;
struct tree{
int a[N];
int lowbit(int x){
return x&(-x);
}
void update(int p,int x){
for(int i=p;i<=n;i+=lowbit(i))
a[i] += x;
}
int sum(int p){
int res = 0;
for(int i=p;i>0;i-=lowbit(i))
res += a[i];
return res;
}
int query(int l,int r){
return sum(r) - sum(l-1);
}
}ch[30];
string s;
int main(){
cin >> s;
n = s.length();
int m,op,l,r;
char cha;
for(int i=0;i<n;++i){
ch[s[i]-'a'].update(i+1,1);
}
cin >> m;
while(m--){
cin >> op;
if(op == 1){
cin >> l >> cha;
ch[s[l-1]-'a'].update(l,-1);
s[l-1] = cha;
ch[s[l-1]-'a'].update(l,1);
}else{
cin >> l >> r;
int ans = 0;
for(int i=0;i<26;++i){
if(ch[i].query(l,r)>0) ans++;
}
printf("%d\n",ans);
}
}
return 0;
}