Pagini recente » Cod sursa (job #2513836) | Cod sursa (job #2931451) | Cod sursa (job #2485296) | Cod sursa (job #2556291) | Cod sursa (job #1121581)
// Include
#include <fstream>
using namespace std;
// Constante
const int sz = (int)1e5+1;
// Functii
inline int leastSignificantBit(int x);
void update(int pos, int val); // Valoarea elementului de pe pozitia pos creste cu val
int query(int pos); // Afla suma de pe intervalul [1, pos]
int search(int val); // Afla, prin cautare binara, pozitia pos astfel incat suma de pe intervalul [1, pos] este egala cu val
// Variabile
ifstream in("aib.in");
ofstream out("aib.out");
int num;
int questions, type;
int tree[sz];
// Main
int main()
{
in >> num >> questions;
int val;
for(int i=1 ; i<=num ; ++i)
{
in >> val;
update(i, val);
}
while(questions--)
{
in >> type;
switch(type)
{
case 0:
{
int pos, val;
in >> pos >> val;
update(pos, val);
break;
}
case 1:
{
int left, right;
in >> left >> right;
out << query(right) - query(left-1) << '\n';
break;
}
case 2:
{
int val;
in >> val;
out << search(val) << '\n';
break;
}
}
}
in.close();
out.close();
return 0;
}
void update(int pos, int val)
{
// La fieccare pas, pozitia creste cu cel mai nesemnificant bit.
// In acest mod voi ajunge la o pozitie a carei suma contine si valoarea de pe pozitia initiala pos
for(; pos<=num ; pos+=leastSignificantBit(pos))
// Valoarea de pe actuala pozitie pos creste cu val
tree[pos] += val;
}
int query(int pos)
{
// Suma de pe intervalul [1, pos]
int sum = 0;
// La fieccare pas, pozitia scade cu cel mai nesemnificant bit.
// In acest mod voi ajunge la o pozitie a carei suma contine si valoarea de pe pozitia initiala pos
for(; pos ; pos&=pos-1)
sum += tree[pos];
return sum;
}
inline int leastSignificantBit(int x)
{
return x ^ (x&(x-1));
}
int search(int val)
{
// Capetele intervalului curent
int left = 1, right = num;
// Caut in intervalul [left, right] atat timp cat intervalul contine cel putin un element (atat timp cat mai exista intervalul)
while(left <= right)
{
// Mijlocul intervalului
int mid = (left + right) / 2;
// Suma de pe intervalul [1, mid]
int midVal = query(mid);
// Daca valoarea din mijloc este chiar valoarea cautata, inseamna ca pozitia cautata este chiar mijlocul
if(midVal == val)
return mid;
// In caz contrar, ma uit in care dintre cele doua intervale ([left, mid-1] sau [mid+1, right]) trebuie sa caut
if(val < midVal)
right = mid-1;
else
left = mid+1;
}
// Daca am ajuns aici (la un interval nul), inseamna ca nu exista pos astfel incat suma de pe intervalul [1, pos] sa fie val
return -1;
}