下午
內容:STL 差分字首和倍增
1. STL
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdio>
#include <set>
#include <map>
#include <unordered_map>
#include <bitset>
using namespace std;
void text(){
vector<int>v;
vector<int>A(5);
vector<int>B(5,3);
vector<int>C={1,2,3};
for(vector<int>::iterator it=A.begin();it!=A.end();it++)cout<<*it<<" ";
puts("");
for(auto it:B)cout<<it<<" ";
puts("");
for(int i=0;i<(int)C.size();i++)cout<<C[i]<<" ";
puts("");
int n;
cin >> n;
v.resize(100);
cout<<(int)v.size()<<"\n";//unsigned
cout<<(int)v.capacity()<<"\n";
for(int i=1;i<=n;i++)
v.push_back(i);
cout<<(int)v.size()<<"\n";//unsigned
cout<<(int)v.capacity()<<"\n";
v.shrink_to_fit();
cout<<(int)v.capacity()<<"\n";
v.push_back(2);
cout<<(int)v.size()<<"\n";
cout<<(int)v.capacity()<<"\n";
v.clear();
cout<<(int)v.capacity()<<"\n";
vector<int>().swap(v);
cout<<(int)v.capacity()<<"\n";
}
namespace basic
{
basic_string<int>v;
void test()
{
int n;
cin >> n;
v.resize(100);
cout<<(int)v.size()<<"\n";//unsigned
cout<<(int)v.capacity()<<"\n";
for(int i=1;i<=n;i++)
v.push_back(i);
cout<<(int)v.size()<<"\n";//unsigned
cout<<(int)v.capacity()<<"\n";
v.shrink_to_fit();
cout<<(int)v.capacity()<<"\n";
v.push_back(2);
cout<<(int)v.size()<<"\n";
cout<<(int)v.capacity()<<"\n";
v.clear();
cout<<(int)v.capacity()<<"\n";
basic_string<int>().swap(v);
cout<<(int)v.capacity()<<"\n";
basic_string<int>A={2,3,4};
basic_string<int>B={2,3,4};
for(auto it:A)cout<<it<<" ";
puts("");
A=A+B;
for(auto it:A)cout<<it<<" ";
puts("");
//string
cout<<A.find({4,2})<<"\n";
}
}
namespace se
{
set<int>A;
multiset<int>B;//set如果插入重複的元素會自動銷燬 , 而multiset不會
void test()
{
for(int i=1;i<=3;i++)
{
A.insert(i);//pair <bool,iterator>
A.insert(i);
B.insert(i);//指標 iterator
B.insert(i);
}
for(auto it:A)cout<<it<<" ";
puts("");
for(auto it:B)cout<<it<<" ";
puts("");
multiset<int>::iterator x=B.lower_bound(0);
multiset<int>::iterator y=B.find(2);
B.erase(x);
for(auto it:B)cout<<it<<" ";
puts("");
B.erase(3);
for(auto it:B)cout<<it<<" ";
puts("");
cout<<(int)B.size()<<"\n";
cout<<(int)B.count(2)<<"\n";
A.clear(),B.clear();
//不能陣列下標訪問。
}
}
namespace ma
{
map<int,int>A;
unordered_map<int,int>B;
void test()
{
for(int i=1;i<=3;i++)A[i]=i-1,B[i]=i-1;
for(auto it:A)cout<<it.first<<" "<<it.second<<"\n";
puts("");
auto it=A.find(2);//key
cout<<A[4]<<"\n";
A.clear(),B.clear();
}
}
namespace bit
{
bitset<10>bit,bb;
void test()
{
bit[5]=1;
cout<<bit<<"\n";
bit.flip();
bit<<=3;
cout<<bit<<"\n";
bb[1]=1;
bb[4]=1;
cout<<bb<<"\n";
bit^=bb;
cout<<bit<<"\n";
int A=bit._Find_first();
cout<<A<<"\n";
cout<<bit._Find_next(A)<<"\n";
}
}
int main(){
vector<int> a = {1,2,3};
for(auto it:a){
cout << it << " ";
}
text();
basic::test();
basic_string<int>aa = {1, 2, 3};//標頭檔案在iostream
for(auto it:aa){
cout << it << " ";
}
return 0;
}
2. 差分字首和
不難,可以解決區間問題
T1 求區間和
std:
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdio>
#include <set>
#include <map>
#include <unordered_map>
#include <bitset>
using namespace std;
const int MAXX = 1e5 + 10;
int a[MAXX], n;
int main(){
cin >> n;
for(int i = 1;i <= n;i++){
int x;
cin >> x;
a[i] = x + a[i - 1];
}
int q;
cin >> q;
while(q--){
int l, r;
cin >> l >> r;
cout << a[r] - a[l - 1] << '\n';
}
return 0;
}
記錄
差分
實現:對於每個區間 \([l, r]\),讓 \(a_l\) 加上 \(v\),\(a_r+1\) 減去 \(v\)。
最大加權矩形
給定一個 \(n \cdot n\) 的矩形,詢問這個矩形內部和最大的一個子子矩形,這個子矩形的和是多少?
\(n ≤ 120\)
std:
const int xx=1005;
int n,q;
ll a[xx][xx];
int main(){
n=read();
for(int i=l;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=read();
ll ma=0;
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
for(int i=x;i<=n;i++)
for(int j=y;j<=n;j++)
ma=max(ma,a[i][j]+a[x-1][y-1]-a[i][y-1]-a[x-1][j]);
cout<<ma<<"\n";
return 0;
}
二維陣列字首和
T2 地毯
問題簡述:
在 \(n\times n\) 的格子上有 \(m\) 個地毯。
給出這些地毯的資訊,問每個點被多少個地毯覆蓋。
std:
#include <iostream>
#define maxn 1005
int n,m,a[maxn][maxn];
int main(){
std::cin.tie(0)->sync_with_stdio(0);
std::cin >> n >> m;
for (int i = 1;i <= m;i++){
int x1,y1,x2,y2;
std::cin >> x1 >> y1 >> x2 >> y2;
for (int j = x1;j <= x2;j++)
for (int k = y1;k <= y2;k++)
a[j][k]++;
}
for (int i = 1;i <= n;i++){
for (int j = 1;j <= n;j++)
std::cout << a[i][j] << ' ';
std::cout << '\n';
}
return 0;
}
記錄
倍增(ST 表)
可解決的問題:區間極值
問題簡述:給定一個長度為 \(N\) 的數列,和 $ M $ 次詢問,求出每一次詢問的區間內數字的最大值。
std:
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdio>
#include <set>
#include <map>
#include <unordered_map>
#include <bitset>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int MAXN = 100005;
int n, m;
int a[MAXN], f[MAXN][21];
int main(){
n = read(), m = read();
for(int i = 1;i <= n;i++){
a[i] = read();
f[i][0] = a[i];
}
for(int j = 1;j <= 20;j++){
for(int i = 1;i <= n;i++){
if(i + (1 << j) - 1 <= n){
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
}
while(m--){
int l = read(), r = read();
int k = __lg(r - l + 1);
cout << max(f[l][k], f[r - (1 << k) + 1][k]) << '\n';
}
return 0;
}