天天看點

A - 敵兵布陣 (線段樹基礎)

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define e 2.718281828
#define rp(i,s,t) for (i = (s); i <= (t); i++)
#define RP(i,s,t) for (i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define push_back() pb()
#define pair<int,int> pii;
#define fastIn                    \
    ios_base::sync_with_stdio(0); \
    cin.tie(0);
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
inline void write(int n)
{
    if(n<0)
    {
        putchar('-');
        n=-n;
    }
    if(n>=10)
        write(n/10);
    putchar(n%10+'0');
}
const int N=1e5+7;
int a[N],c[N];
char s[10];
int n;
int lowbit(int x){
    return x&(-x);
}
int query(int x){
    int sum=0;
    while(x>0){
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
void update(int index,int x){
    while(index<=n){
        c[index]+=x;
        index+=lowbit(index);
    }
}
int main(){
	int T=read(),i,Case=0;
    while(T--){
        n=read();
        mst(a,0);
        mst(c,0);
        rp(i,1,n){
            a[i]=read();
            update(i,a[i]);
        } 
        printf("Case %d:\n",++Case);
        while(~scanf("%s",s)){
            if(s[0]=='Q'){
                int l=read(),r=read();
                write(query(r)-query(l-1));
                printf("\n");
            } 
            else if(s[0]=='A'){
                int x=read(),delta=read();
                update(x,delta);
            }
            else if(s[0]=='S'){
                int x=read(),delta=read();
                update(x,-delta);
            }
            else if(s[0]=='E') break;
        }
    }  
	return 0;
}
           

C國的死對頭A國這段時間正在進行軍事演習,是以C國間諜頭子Derek和他手下Tidy又開始忙乎了。A國在海岸線沿直線布置了N個工兵營地,Derek和Tidy的任務就是要監視這些工兵營地的活動情況。由于采取了某種先進的監測手段,是以每個工兵營地的人數C國都掌握的一清二楚,每個工兵營地的人數都有可能發生變動,可能增加或減少若幹人手,但這些都逃不過C國的監視。

中央情報局要研究敵人究竟演習什麼戰術,是以Tidy要随時向Derek彙報某一段連續的工兵營地一共有多少人,例如Derek問:“Tidy,馬上彙報第3個營地到第10個營地共有多少人!”Tidy就要馬上開始計算這一段的總人數并彙報。但敵兵營地的人數經常變動,而Derek每次詢問的段都不一樣,是以Tidy不得不每次都一個一個營地的去數,很快就精疲力盡了,Derek對Tidy的計算速度越來越不滿:"你個死肥仔,算得這麼慢,我炒你鱿魚!”Tidy想:“你自己來算算看,這可真是一項累人的工作!我恨不得你炒我鱿魚呢!”無奈之下,Tidy隻好打電話向計算機專家Windbreaker求救,Windbreaker說:“死肥仔,叫你平時做多點acm題和看多點算法書,現在嘗到苦果了吧!”Tidy說:"我知錯了。。。"但Windbreaker已經挂掉電話了。Tidy很苦惱,這麼算他真的會崩潰的,聰明的讀者,你能寫個程式幫他完成這項工作嗎?不過如果你的程式效率不夠高的話,Tidy還是會受到Derek的責罵的.

Input

第一行一個整數T,表示有T組資料。

每組資料第一行一個正整數N(N<=50000),表示敵人有N個工兵營地,接下來有N個正整數,第i個正整數ai代表第i個工兵營地裡開始時有ai個人(1<=ai<=50)。

接下來每行有一條指令,指令有4種形式:

(1) Add i j,i和j為正整數,表示第i個營地增加j個人(j不超過30)

(2)Sub i j ,i和j為正整數,表示第i個營地減少j個人(j不超過30);

(3)Query i j ,i和j為正整數,i<=j,表示詢問第i到第j個營地的總人數;

(4)End 表示結束,這條指令在每組資料最後出現;

每組資料最多有40000條指令

Output

對第i組資料,首先輸出“Case i:”和回車,

對于每個Query詢問,輸出一個整數并回車,表示詢問的段中的總人數,這個數保持在int以内。

Sample Input

1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End 
           

Sample Output

Case 1:
6
33
59
           
/*
  基礎線段樹模闆題
  而且不涉及區間更新;
  隻是簡單的單點更新,
  區間求和。
  這裡借鑒了胡浩的線段樹模闆 
*/ 
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
  //這裡的預處理使得代碼更加簡潔 
const int maxn = 5e4+3;
using namespace std;
int sum[maxn*4];
int a,b;
void push_up(int rt)//向上傳遞,把目前結點的資訊更新給父節點 
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
	if(l==r)
	{
		scanf("%d",&sum[rt]);
		return ;
	}
	int m = (l+r)/2;
	build(lson);
	build(rson);
	push_up(rt);
}
int query(int L,int R,int l,int r,int rt)//區間求和 
{
	if(L<=l&&r<=R)
	   return sum[rt];
	int m = (l+r)/2;
	int ans=0;
	if(L<=m) ans+=query(L,R,lson);
	if(m<R) ans+=query(L,R,rson);
	return ans;
}
void sub(int l,int r,int rt)//單點更新——減少 
{
	if(l==r)
	{
		sum[rt]-=b;
		return ;
	}
	int m = (l+r)/2;
	if(a<=m) sub(lson);
	else  sub(rson);
	push_up(rt);
}
void add(int l,int r,int rt)//單點更新——增加 
{
	if(l==r)
	{
		sum[rt]+=b;
		return ;
	}
	int m = (l+r)/2;
	if(a<=m) add(lson);
	else  add(rson);
	push_up(rt);
}
int main(int argc, char** argv) {
	int T;
	scanf("%d",&T);
	for(int cas = 1;cas<=T;cas++)
	{
		printf("Case %d:\n",cas);
		int n; 
		scanf("%d",&n);
		build(1,n,1);
		char str[10];
		while(scanf("%s",str))
		{
			if(str[0]=='E') break;
			scanf("%d %d",&a,&b);
			if(str[0]=='Q')
			    printf("%d\n",query(a,b,1,n,1));
			else if(str[0]=='S')
				sub(1,n,1);
			else 
			    add(1,n,1);
		}
	}
	return 0;
}
           

 下面給出樹狀數組的做法

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#define PI atan(1.0)*4
#define e 2.718281828
#define rp(i,s,t) for (i = (s); i <= (t); i++)
#define RP(i,s,t) for (i = (t); i >= (s); i--)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define push_back() pb()
#define pair<int,int> pii;
#define fastIn                    \
    ios_base::sync_with_stdio(0); \
    cin.tie(0);
using namespace std;
inline int read()
{
    int a=0,b=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
            b=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        a=(a<<3)+(a<<1)+c-'0';
        c=getchar();
    }
    return a*b;
}
inline void write(int n)
{
    if(n<0)
    {
        putchar('-');
        n=-n;
    }
    if(n>=10)
        write(n/10);
    putchar(n%10+'0');
}
const int N=1e5+7;
int a[N],c[N];
char s[10];
int n;
int lowbit(int x){
    return x&(-x);
}
int query(int x){
    int sum=0;
    while(x>0){
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
void update(int index,int x){
    while(index<=n){
        c[index]+=x;
        index+=lowbit(index);
    }
}
int main(){
	int T=read(),i,Case=0;
    while(T--){
        n=read();
        mst(a,0);
        mst(c,0);
        rp(i,1,n){
            a[i]=read();
            update(i,a[i]);
        } 
        printf("Case %d:\n",++Case);
        while(~scanf("%s",s)){
            if(s[0]=='Q'){
                int l=read(),r=read();
                write(query(r)-query(l-1));
                printf("\n");
            } 
            else if(s[0]=='A'){
                int x=read(),delta=read();
                update(x,delta);
            }
            else if(s[0]=='S'){
                int x=read(),delta=read();
                update(x,-delta);
            }
            else if(s[0]=='E') break;
        }
    }  
	return 0;
}
           

繼續閱讀