预期 | 一测 | ||
a | 100 | 100 | 0 |
b | 100 | 20 | -80 |
c | 100 | 63 | -37 |
d | 100 | 100 | 0 |
e | 100 | 100 | 0 |
f | 100 | 100 | 0 |
总分 | 600 | 483 | -117 |
问题 A: 校门外的树(Vijos P1448)
分别用两个树状数组维护左端点和右端点的数量,然后对于每一询问,查询右端点以前的左括号有多少个,减去左端点以前的右括号有多少个相减就是答案;
#include<bits/stdc++.h>
using namespace std;
#define N 500001
#define LL long long
int c[N+10],a[N+10];
int n,m;
LL ask1(int x){
LL ret=0;
for(;x;x-=x&-x) ret+=c[x];
return ret;
}
LL ask2(int x){
LL ret=0;
for(;x;x-=x&-x) ret+=a[x];
return ret;
}
LL add1(int x,int y){
for(;x<=n;x+=x&-x) c[x]+=y;
}
LL add2(int x,int y){
for(;x<=n;x+=x&-x) a[x]+=y;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==1) add1(r,1),add2(l,1);
else printf("%d\n",ask2(r)-ask1(l-1));
}
return 0;
}
/*
5 3
1 1 2
1 3 4
2 2 3
*/
问题 B: 堆蛋糕
问题 C: 蚯蚓
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, q, u, v, t, delta = 0;
priority_queue<ll> pq;
queue<ll> q1, q2;
int main() {
cin >> n >> m >> q >> u >> v >> t;
for (int i = 1; i <= n; i++) {
ll a;
scanf("%lld", &a);
pq.push(a);
}
for (int i = 1; i <= m; i++) {
ll maxx = -INF;
int w;
if (pq.size() && maxx < pq.top()) {
maxx = pq.top();
w = 0;
}
if (q1.size() && maxx < q1.front()) {
maxx = q1.front();
w = 1;
}
if (q2.size() && maxx < q2.front()) {
maxx = q2.front();
w = 2;
}
if (w == 1) q1.pop();
else if (w == 2) q2.pop();
else pq.pop();
maxx += delta;
q1.push(maxx * u / v - delta - q);
q2.push(maxx - maxx * u / v - delta - q);
delta += q;
if (i % t == 0) printf("%lld ", maxx);
}
cout << endl;
for (int i = 1; i <= n + m; i++) {
ll maxx = -INF;
int w;
if (pq.size() && maxx < pq.top()) {
maxx = pq.top();
w = 0;
}
if (q1.size() && maxx < q1.front()) {
maxx = q1.front();
w = 1;
}
if (q2.size() && maxx < q2.front()) {
maxx = q2.front();
w = 2;
}
if (w == 1) q1.pop();
else if (w == 2) q2.pop();
else pq.pop();
if (i % t == 0) printf("%lld ", maxx + delta);
}
cout << endl;
return 0;
}
问题 D: 清点人数
树状数组板题
问题 E: 打鼹鼠
用一个二维树状数组维护从0,0到x,y有多少只鼹鼠,操作与一维大同小异
#include<bits/stdc++.h>
using namespace std;
#define N 1024
#define LL long long
LL c[N+10][N+10];
int n,m;
LL ask(int x,int y){
LL ret=0;
for(;x;x-=x&-x)
for(int i=y;i;i-=i&-i)
ret+=c[x][i];
return ret;
}
LL add(int x,int y,int k){
for(;x<=n;x+=x&-x)
for(int i=y;i<=n;i+=i&-i)
c[x][i]+=k;
}
int main(){
scanf("%d",&n);
while(cin>>m && m!=3){
int x,y,k,a,b;
if(m==1){
scanf("%d%d%d",&x,&y,&k);
x++,y++;
add(x,y,k);
} else {
scanf("%d%d%d%d",&x,&y,&a,&b);
x++,y++,a++,b++;
printf("%lld\n",ask(a,b)+ask(x-1,y-1)-ask(x-1,b)-ask(a,y-1));
}
}
return 0;
}
/*
4
1 2 2 5
2 0 0 2 3
3
*/
问题 F: 数列区间最大值
ST表板题,记得预处理log数组,c++自带的太慢了。
#include<bits/stdc++.h>
using namespace std;
#define N 100010
int f[N][20];
int lg[N];
int a[N];
int n,m,u,v;
void pre(){
for(int i=2;i<=n;++i) lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;++i) scanf("%d",a+i),f[i][0]=a[i];
int t=lg[n];
for(int j=1;j<=t;++j)
for(int i=1;i<=n-(1<<j)+1;++i)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int query(int l,int r){
int k=lg[r-l+1];
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main(){
scanf("%d%d",&n,&m);
pre();
for(int i=1;i<=m;++i){
scanf("%d%d",&u,&v);
printf("%d\n",query(u,v));
}
}
/*
10 3
3 2 4 5 6 8 1 2 9 7
1 4
3 8
1 10
*/