T1:模拟
void solve(){
int a[3];
char s[3];
cin >> s[0] >> s[1]>>s[2];
if(s[0]=='>'){
if(s[1]=='>'){
if(s[2]=='>'){// >>>
cout <<"B"<<endl;
}
else{//>><
cout << "C"<<endl;
}
}
//><>不存在
else{//><<
cout <<"A"<<endl;
}
}
else{
if(s[1]=='>'){//<>
if(s[2]=='>'){//<>>
cout <<"A"<<endl;
}
}
else{
if(s[2]=='>'){
cout <<"C"<<endl;
}
else{
cout <<"B"<<endl;
}
}
}
}
T2:找每次如果是M且之前没有过M的,模拟即可
void solve(){
cin >> n >> m;
for(int i=0;i<m;i++){
cin >> a[i] >> b[i];
}
for(int i=0;i<m;i++){
if(b[i]=='M'){
++st[a[i]-1];
if(st[a[i]-1]==1){
yes;
continue;
}
}
no;
}
}
T3:图的同构
VVI add(VPII e, int n) {
VVI jj(n, VI(n, 0));
for (auto ee : e) {
int u = ee.first;
int v = ee.second;
jj[u][v] = 1;
jj[v][u] = 1;
}
return jj;
}
int fc(VVI gg,VVI hh,VVI c,VI p) {
int tot = 0;
for (int i = 0; i < gg.size(); ++i) {
for (int j = i + 1; j < N; ++j) {
int u = p[i];
int v = p[j];
if (gg[u][v] != hh[i][j]) {
tot += c[i][j];
}
}
}
return tot;
}
void solve(){
int n;
cin >> n;
int g;
cin >> g;
VPII eg(g+10);
for (int i = 0; i < g; i++) {
int u, v;
cin >> u >> v;
eg[i] = {u - 1, v - 1};
}
int h;
cin >> h;
VPII eh(h);
for (int i = 0; i < h; i++) {
int a, b;
cin >> a >> b;
eh[i] = {a - 1, b - 1};
}
VVI c(n, VI(n, 0));
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
cin >> c[i][j];
}
}
VVI gg = add(eg, n);
VVI hh = add(eh, n);
VI p(n);
iota(p.begin(), p.end(), 0);
int ans = 0x3f3f3f3f;
ans = min(ans, fc(gg, hh, c, p));
while (next_permutation(p.begin(), p.end())){
ans = min(ans, fc(gg, hh, c, p));
}
cout << ans << endl;
}
T4:阅读题意很显然是使用前缀和,但问题在于a[i]范围是LL如果按照普通方法开前缀肯定会爆MLE,结局的两种方法是在LL上使用二分,其次是离散化,这里提供LL的vector版本
void solve(){
cin >> n;
VI x;
VI p;
for (int i = 0; i < n; i++) {
int xx;
cin >> xx;
x.push_back(xx);
}
for (int i = 0; i < n; i++) {
int pp;
cin >> pp;
p.push_back(pp);
}
for (int i = 0; i < n; ++i) {
s[i + 1] = s[i] + p[i];
}
cin >> q;
while (q--) {
int L, R;
cin >> L >> R;
VI::iterator itl = lower_bound(x.begin(), x.end(), L);
VI::iterator itr = upper_bound(x.begin(), x.end(), R);
int l = distance(x.begin(), itl);
int r = distance(x.begin(), itr) - 1;
if (l <= r && l < n && r >= 0) {
LL ans = s[r + 1] - s[l];
cout << ans <<endl;
} else {
cout << 0 << endl;
}
}
}
T5:首先想到了滑动窗口和unordered_set的Onlogn,但实际会On2TLE
void solve(){
cin >> n;
read(a,n);
LL ans = 0;
for (int i = 0; i < n; i++) {
unordered_set<int> alls;
int temp = 0;
for (int j = i; j < n; j++) {
if (alls.find(a[j]) == alls.end()) {
alls.insert(a[j]);
temp++;
}
ans += temp;
}
}
cout << ans << endl;
}
正解:考虑互补事件先计算不包含 i 的子数组的个数,然后从所有数组中减去总和。在 A 的两端插入 i,按升序排列的索引 x 和 Ax = i 就表示为 x=(x0,x1....x_Ci+1 = N+1)不包含 i 的子数组数等于
(左端为 x0+1 或更大,右端为 x1-1 或更小的子数组的个数)+ (左端大于等于 x1+1 且右端小于等于 x2-1 的子数组个数)+...........+ (左端为 x{Ci}+1 或以上,右端为 x{Ci+1}-1 或以下的子数组个数)
void solve(){
int n;
LL ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
ans += 1LL * (i - p[a[i]]) * (n - i + 1);
p[a[i]] = i;
}
cout << ans;
}