我正在尝试解决 this使用二叉索引树的 UVA 中的问题:
Problem H
Ahoy, Pirates!
Input: Standard Input
Output: Standard Output
In the ancient pirate ages, the Pirate Land was divided into two teams of pirates,
namely, the Buccaneer and the Barbary pirates. Each pirate’s team was not fixed,
sometimes the opponent pirates attacked and he was taken away to the other pirate team.
All on a sudden a magician appeared in the Pirate Land, where he was making transition
of pirates from their team to other team at his own will. Of course, handy spells
were used. The process of changing team was known as mutating.
There were N pirates and all of the pirates have a unique id from 0 to N-1.
The great magician could mutate a bunch of pirates with consecutive id’s to
another one.
Suppose there were 100 pirates in the pirate land and all of them were
Barbary pirates, then the magician could cast a spell to change pirates with
id’s from 10 to 33 to Buccaneer pirates. Then the whole pirate land would
have 24 Buccaneer and 76 Barbary pirates.
The magician was very fast casting the spell. Once, God started to dislike this.
God had favor for the Buccaneer pirates and God asked the magician, “Tell me,
how many of the pirates of index from 2 to 30 are Buccaneer pirates?”. Now the
magician was puzzled as he was only efficient in casting spells, not in counting J
Being clever enough, the magician captured a clever man from the Earth Land.
And unfortunately it’s you! Now you have to answer the God’s questions.
Input
The first line of input will contain number of test cases T.
For each test case:
The first part of the description will be of the pirate land.
There could be up to N (1<=N<=1024000) pirates. Each pirate is either
assigned to Buccaneer or Barbary Pirate. Buccaneer pirates are described
by ‘1’ (ONE) and Barbary pirates are described by ‘0’ (ZERO). You have to
build a string of the pirates’ description. Each case starts with an integer
M (M<=100), where M pair lines follow. In each pair of lines (we call it a set),
first has an integer T (T <= 200) and next one has a nonempty string Pirates
(consisting of 0 and 1, 0 for Barbary, 1 for Buccaneer, has maximum length of 50).
For each pair concatenate the string Pirates, T times. Concatenate all the
resulting M sets of strings to build the pirate description. The final
concatenated string describes the pirates from index 0 to end (N-1 for N pirates).
Now the next part of the input will contain queries.
First line of next part has an integer Q describing number of queries.
Each subsequence Q (1<=Q<=1000) lines describe each query. Each query has a
string F or E or I or S and two integers, a and b denoting indexes.
The meaning of the query string are follows:
F a b, means, mutate the pirates from index a to b to Buccaneer Pirates.
E a b, means, mutate the pirates from index a to b to Barbary Pirates.
I a b, means, mutate the pirates from index a to b to inverse pirates.
S a b, means, “God’s query” God is asking a question:
“Tell me, how many Buccaneer pirates are there from index a to b?”
(a <= b, 0 <= a < n, 0 <= b < n, index range are inclusive)
Output
For each test print the case number as the sample output suggests.
Then for each of “God’s query”, output the query number, colon (:) and
a space and the answer to the query as the sample suggest.
╔══════════════╦═════════════════════════╗
║ Sample Input ║ Output for Sample Input ║
╠══════════════╬═════════════════════════╣
║ 2 ║ Case 1: ║
║ 2 ║ Q1: 5 ║
║ 5 ║ Q2: 1 ║
║ 10 ║ Case 2: ║
║ 2 ║ Q1: 0 ║
║ 1000 ║ ║
║ 5 ║ ║
║ F 0 17 ║ ║
║ I 0 5 ║ ║
║ S 1 10 ║ ║
║ E 4 9 ║ ║
║ S 2 10 ║ ║
║ 3 ║ ║
║ 3 ║ ║
║ 1 ║ ║
║ 4 ║ ║
║ 0 ║ ║
║ 2 ║ ║
║ 0 ║ ║
║ 2 ║ ║
║ I 0 2 ║ ║
║ S 0 8 ║ ║
╚══════════════╩═════════════════════════╝
Explanation:
Case1:
The pirate land is as follows (N = 18)
101010101010001000
Before God’s first query it was as follows
000000111111111111
Case 2:
The pirate land is as follows (N=9)
111000000
它是关于将一个范围的值递增或递减到 1 或 0,查询与 fenwick tree 一样。
我知道如何在树中的特定位置更新。
在更新一个范围时,我只是对该范围内的每个元素使用一个循环来更新到 1 或 0。但这花费了太多时间。
有没有其他方法可以在分域树中进行范围更新?
实际上它是一个由 1' 和 0 组成的数组,没有任何其他内容,更新过程仅包括将范围 [a,b] 更新为 1,0 或取反。 这是我的代码:
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
typedef vector<int> vi;
class bit{
public:
bit(int n,string strt):s(strt){ ftBuc.assign(n+2,0); }
void adjust(int k,int v){
if(v=='1'&&s[k] == '1')
return;
else if(v=='0' && s[k] == '0')
return;
else if(v=='1'&&s[k] == '0')
{ s[k] = '1'; for(;k<(int)ftBuc.size();k += leastSig1(k)) ftBuc[k]+=1; }
else if(v=='0' && s[k] == '1' )
{ s[k] = '0'; for(;k<(int)ftBuc.size();k += leastSig1(k)) ftBuc[k]-=1; }
}
int rsq(int a,int b) { return rsq(b)-(a==1?0:rsq(a-1));}
string s;
int rsq(int b) { int sum = 0; for(; b ; b-=leastSig1(b)) sum+=ftBuc[b]; return sum;}
vi ftBuc;
int leastSig1(int i) {return i&(-i);}
};
int main()
{
int t;
cin>>t;
for(int test=1;test<=t;++test)
{
int m;
cin>>m;
string s;
while(m--)
{
int T;
cin>>T;
string temp;
cin>>temp;
while(T--)
s.append(temp);
}
int n = s.size();
bit ft(n+2,string(n+2,'0'));
for(int i = 1;i<=n;++i)
ft.adjust(i,s[i-1]);
int q;
cin>>q;
int asks = 1;
printf("Case %d:\n",test);
while(q--)
{
char c;
int i,j;
cin>>c>>i>>j;
if(c=='F')
{
for(int k=i+1;k<=j+1;++k)
ft.adjust(k,'1');
}
else if(c=='E')
{
for(int k=i+1;k<=j+1;++k)
ft.adjust(k,'0');
}
else if(c == 'I')
{
for(int k=i+1;k<=j+1;++k)
{
if(ft.s[k] == '1')
ft.adjust(k,'0');
else
ft.adjust(k,'1');
}
}
else if(c=='S')
printf("Q%d: %d\n",asks++,ft.rsq(i+1,j+1));
}
}
}
最佳答案
BIT 可以在 3 种模式之一中运行:
- 点更新和范围查询
- 范围更新和点查询
- 范围更新和范围查询
我已经用 BIT 解释了范围更新并在此处提供了实现:http://kartikkukreja.wordpress.com/2013/12/02/range-updates-with-bit-fenwick-tree/
关于algorithm - 如何在二叉索引树或分域树中进行范围更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18065238/