HDU 1166 敌兵布阵
最简单的树状数组点更新,区间查询
#include<cstdio>
#include<cstring>
using namespace std;
int c[100001];
int n, m;
void add(int k, int s){
for(int i = k; i <= n; i += i & (-i)){
c[i] += s;
}
}
int sum(int k){
int t = 0;
for(int i = k; i > 0; i -= i & (-i)){
t += c[i];
}
return t;
}
int main(){
int T;
scanf("%d", &T);
for(int kase = 1; kase <= T; kase++){
printf("Case %d:\n", kase);
scanf("%d", &n);
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; i++){
int k;
scanf("%d", &k);
add(i,k);
}
char s[10];
int x, y;
while(scanf("%s", s), s[0] != 'E'){
scanf("%d%d", &x, &y);
if(s[0] == 'A') {
add(x, y);
}else if(s[0] == 'S'){
add(x, -y);
}
else printf("%d\n", sum(y) - sum(x - 1));
}
}
return 0;
}
/
LightOJ 1112 Curious Robin Hood
这道题和上一道相比非常类似
#include<stdio.h>
#include<string.h>
int n;
int c[100010];
int lowbit(int x)
{
return x&(-x);
}
void update(int pos,int i)
{
while(pos<=n)
{
c[pos]+=i;
pos+=lowbit(pos);
}
}
int sum(int pos)
{
int ans=0;
while(pos)
{
ans+=c[pos];
pos-=lowbit(pos);
}
return ans;
}
int main()
{
int T,i,k,t=0,q;
scanf("%d",&T);
while(T--)
{
memset(c,0,sizeof(c));
printf("Case %d:\n",++t);
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%d",&k);
update(i,k);
}
int m,a,b;
while(q--)
{
scanf("%d",&m);
if(m==1)
{
scanf("%d",&a);
a++;
printf("%d\n",sum(a)-sum(a-1));
update(a,sum(a-1)-sum(a));
}
else if(m==2)
{
scanf("%d%d",&a,&b);
a++;
update(a,b);
}
else if(m==3)
{
scanf("%d%d",&a,&b);
a++;
b++;
printf("%d\n",sum(b)-sum(a-1));
}
}
}
return 0;
}
LightOJ 1080 Binary Simulation
典型的树状数组区间更新点查询,查询的时候是查询的每个点的反转次数,然后再加上初始值即可
对2取余就可以得到答案
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 500005
#define lowbit(i) (i&(-i))
using namespace std;
int a[maxn], n, len, val;
char ch[maxn];
void update(int pos, int v) {
while(pos<=len) {
a[pos] += v;
pos += lowbit(pos);
}
}
long long sum (int pos) {
long long ans = 0;
while(pos>0) {
ans += a[pos];
pos -= lowbit(pos);
}
return ans;
}
int main (void) {
int T, k, kase=0;
scanf("%d", &T);
while(T--) {
printf("Case %d:\n", ++kase);
memset(a, 0, sizeof(a));
memset(ch, 0, sizeof(ch));
scanf("%s", ch+1);
len = strlen(ch+1);
char op[15];
scanf("%d", &k);
for(int i=1; i<=k; ++i) {
scanf("%s", op);
int b, c;
if(op[0] == 'I') {
scanf("%d %d", &b, &c);
update(b, 1);
update(c+1, -1);
} else if(op[0] == 'Q') {
scanf("%d", &b);
int val = sum(b)+ch[b]-'0';
if(val%2)
printf("1\n");
else
printf("0\n");
}
}
}
return 0;
}
LightOJ 1085 All Possible Increasing Subsequences
这题就是求这个序列中有多少个上升序列。
开一个数组s,s[i]记作以第i数为结尾的上升序列的个数。
用一个数组a,存储原数据
然后求s[j]时,遍历1~j-1,s[j] = sum(s[i]){1<=i<j, a[i]<a[j]}
但这样一定超时,所以可以使用树状数组维护小于m的数字有多少个。
但又因为每个数字可能太大,所以可以先离散化
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int M = 1e5 + 20;
const LL N = 1000000007;
struct node{
int x, y, z;
node(int _x = 0, int _y = 0):x(_x), y(_y){}
friend bool operator < (const node& a, const node& b){
return a.x < b.x;
}
}a[M];
bool cmp(const node& a, const node& b){
return a.z < b.z;
}
LL C[M];
int n;
inline int LowBit(int x) { return x & (-x);}
inline void Update(int x, LL d){
while(x <= n){
C[x] += d;
C[x] %= N;
x += LowBit(x);
}
}
inline LL GetSum(int x){
LL sum = 0;
while(x > 0){
sum += C[x];
sum %= N;
x -= LowBit(x);
}
return sum;
}
int main()
{
int t, cas = 1, m;
cin >> t;
while(t--){
cin >> m, n = 1;
LL ans = 0, buf;
for(int i = 1; i <= m; i++) scanf("%d", &a[i].x), a[i].z = i;
sort(a+1, a+1+m);
for(int i = 1; i <= m; i++){
if(i > 1 && a[i].x == a[i-1].x) a[i].y = a[i-1].y;
else a[i].y = n++;
}
for(int i = 0; i < n+10; i++) C[i] = 0;
sort(a+1, a+1+m, cmp);//完成了离散化
for(int i = 1; i <= m; i++){
buf = GetSum(a[i].y - 1)+1;
ans += buf, ans %= N;
Update(a[i].y, buf);
}
printf("Case %d: %lld\n", cas++, ans);
}
return 0;
}
LightOJ 1266 Points in Rectangle
一道典型的二维树状数组。
二维树状数组无论代码还是理论都和一维差不多
#include <bits/stdc++.h>
using namespace std;
const int M = 1e+3 + 40;
int n, m;
long long C[M][M];
bool vis[M][M];
inline int LowBit(int x){ return x & (-x);}
inline void Update(int x, int y, int d){
for(int i = x; i <= n; i += LowBit(i))
for(int j = y; j <= m; j += LowBit(j))
C[i][j] += d;
}
inline long long GetSum(int x, int y){
long long sum = 0;
for(int i = x; i > 0; i -= LowBit(i))
for(int j = y; j > 0; j -= LowBit(j))
sum += C[i][j];
return sum;
}
int main()
{
int t, cas = 1, d, x1, y1, x2, y2, q;
long long s;
cin >> t;
while(t--){
printf("Case %d:\n", cas++);
cin >> q;
n = m = M - 20;
memset(vis, false, sizeof(vis));
memset(C, 0, sizeof(C));
while(q--){
scanf("%d", &d);
if(d){
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1++, x2++, y1++, y2++;
s = GetSum(x2, y2) + GetSum(x1-1, y1-1);
s -= GetSum(x1-1, y2), s-= GetSum(x2, y1-1);
printf("%lld\n", s);
}
else{
scanf("%d%d", &x1, &y1), x1++, y1++;
if(!vis[x1][y1]){
vis[x1][y1] = true;
Update(x1, y1, 1);
}
}
}
}
return 0;
}
HDU 5775 Bubble Sort
这道题和逆序数有关,试试找找规律,我以前是靠猜把这题过了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lowbit(x) (x&(-x))
int num[100005],c[100005],res[100005],n;
int getSum(int pos)
{
int res=0;
while(pos>0){
res+=c[pos];
pos-=lowbit(pos);
}
return res;
}
void update(int pos, int val)
{
while(pos<=n){
c[pos]+=val;
pos+=lowbit(pos);
}
}
int main()
{
int T,k,i;
scanf("%d",&T);
for(k=1;k<=T;k++){
memset(res,0,sizeof(res));
memset(c,0,sizeof(c));
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&num[i]);
}
for(i=1;i<=n;i++){
update(num[i],1);
res[num[i]]=i-getSum(num[i]);
if(num[i]>i) res[num[i]]+=num[i]-i;
}
printf("Case #%d:",k);
for(i=1;i<n;i++) printf(" %d",res[i]);
printf(" %d\n",res[n]);
}
return 0;
}
树状数组
最新推荐文章于 2024-09-02 22:25:23 发布