Segment tree with lazy propagation doesn't work - c++

I am trying to implement a segment tree with lazy propagation. The queries I need are:
sum of elements in range [a,b)
elements in range [a, b) become equal to x
add x to elements in range [a,b)
I wrote some code, but it does not work.
a and b goes from 0 to N-1, while the segment tree is 1-indexed
The function add must add x to elements from l (included) to r (not included)
The function add must make elements from l (included) to r (not included) become x.
When one of the above functions meet a node which range is completely inside l and r, then it sets is lazyadd or lazyset to the value to be added to those elements.
Whenever a function meet a node, it checks if it has any lazy update to do, through the functions uplset and upladd, that update the node and change the lazy value of their children.
#include <iostream>
#include <vector>
#include <limits.h>
using namespace std;
struct Node {
long long sum;
long long min;
long long lazyset;
long long lazyadd;
Node() : sum(0), min(INT_MAX), lazyset(0), lazyadd(0) {};
};
vector<Node> tree;
int reals=1; // size of the tree
void init(vector<long long> a) { // build segment tree from vector a
int size = a.size();
while(reals<a.size()) {
reals*=2;
}
tree.resize(2*reals);
for(int i=0;i<a.size();i++) {
tree[reals+i].min=a[i];
tree[reals+i].sum=a[i];
}
for(int i=reals-1;i>0;i--) {
tree[i].sum=tree[2*i].sum+tree[2*i+1].sum;
tree[i].min=min(tree[2*i].min, tree[2*i+1].min);
}
}
void uplset(int k, int x, int y, long long rx) { // lazy set update
int d = y-x;
int lazy = tree[k].lazyset;
tree[k].sum=d*rx;
if(k<reals) {
tree[k*2].lazyset=lazy;
tree[k*2+1].lazyset=lazy;
}
tree[k].lazyset=0;
}
void upladd(int k, int x, int y, long long rx) { // lazy add update
int d = y-x;
int lazy = tree[k].lazyadd;
tree[k].sum+=d*rx;
if(k<reals) {
tree[k*2].lazyadd=lazy;
tree[k*2+1].lazyadd=lazy;
}
tree[k].lazyadd=0;
}
long long rsum(int a, int b, int k, int x, int y) { // sum of elements
if(tree[k].lazyadd!=0) {
upladd(k,x,y,tree[k].lazyadd);
}
if(tree[k].lazyset!=0) {
uplset(k,x,y,tree[k].lazyset);
}
if(b<=x||a>=y) return 0;
if(a<=x&&b>=y) return tree[k].sum;
int d = (x+y)/2;
return rsum(a, b, 2*k, x, d) + rsum(a, b, 2*k+1, d, y);
}
long long get_sum(int l, int r) {
return rsum(l, r, 1, 0, reals);
}
void rladd(int a, int b, int k, int x, int y, long long rx) { // add rx to elements
if(tree[k].lazyadd!=0) {
upladd(k,x,y,tree[k].lazyadd);
}
if(tree[k].lazyset!=0) {
uplset(k,x,y,tree[k].lazyset);
}
if(y<=a||x>=b) return;
if(x>=a&&y<=b) {
tree[k].lazyadd=rx;
} else {
int d=(x+y)/2;
rladd(a,b,2*k,x, d,rx);
rladd(a,b,2*k+1,d, y,rx);
long long uno = tree[k*2].lazyadd ? tree[k*2].sum+tree[k*2].lazyadd*(d-x) : tree[k*2].sum;
long long due = tree[k*2+1].lazyadd ? tree[k*2].sum+tree[k*2+1].lazyadd*(d-x) : tree[k*2+1].sum;
tree[k].sum=uno+due;
}
}
void add(int l, int r, long long x) {
return rladd(l,r,1,0,reals, x);
}
void rlset(int a, int b, int k, int x, int y, long long rx) {
if(tree[k].lazyadd!=0) {
upladd(k,x,y,tree[k].lazyadd);
}
if(tree[k].lazyset!=0) {
uplset(k,x,y,tree[k].lazyset);
}
if(y<=a||x>=b) return;
if(x>=a&&y<=b) {
tree[k].lazyset=rx;
} else {
int d=(x+y)/2;
rlset(a,b,2*k,x, d,rx);
rlset(a,b,2*k+1,d, y,rx);
long long uno = tree[k*2].lazyset ? tree[k*2].lazyset*(d-x) : tree[k*2].sum;
long long due = tree[k*2+1].lazyset ? tree[k*2+1].lazyset*(d-x) : tree[k*2+1].sum;
tree[k].sum=uno+due;
}
}
void set_range(int l, int r, long long x) {
rlset(l,r,1,0,reals,x);
}

Related

Kattis annoyed coworkers problem (self-sorting data structures and a min heap )

Okay so am trying to make a data structure that maintains a heap of data in order to solve within the compile-time limit. https://open.kattis.com/problems/annoyedcoworkers
I might be in over my head since I just started coding in the last year or so and I just learned about sorting and vectors last week and heap data structures yesterday. But I am really interested in solving this problem.
Anyway here goes I first started to solve this problem with selection sort... needless to say it took way too long.
Then I started looking into making a heap data structure that yields values sorted order,
which brought me to priority_queue
After about 9 hours of trying different methods, this is the closest I've gotten to solving the problem.
does anyone have any suggestions as to why after 25/27 test cases my code returns a wrong answer?
Here is my code :
// C++ program to use priority_queue to implement Min Heap
// for user defined class
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// User defined class, coworker
class CoworkerT
{
private:
int a;
int d;
public:
CoworkerT(int _a, int _d)
{
a = _a;
d = _d;
}
int SimAddAD() const
{
int aD;
aD = a + d;
return aD;
}
int AddAD()
{
a = a + d;
return a;
}
int getA() const {
return a;
}
int getD() const {
return d;
}
};
// To compare two coworkers possible a value
class Min
{
public:
int operator() (const CoworkerT& p1, const CoworkerT& p2)
{
return p1.SimAddAD() > p2.SimAddAD();
}
};
//compare two a values between coworkers
class Max
{
public:
int operator() (const CoworkerT& p1, const CoworkerT& p2)
{
return p1.getA() < p2.getA();
}
};
int AskForA() {
int a;
cin >> a;
return a;
}
int AskForD() {
int d;
cin >> d;
return d;
}
priority_queue <CoworkerT, vector<CoworkerT>, Max >
PopulateMax(priority_queue <CoworkerT, vector<CoworkerT>, Max > max,
priority_queue <CoworkerT, vector<CoworkerT>, Min > min) {
while (min.empty() == false)
{
CoworkerT e = min.top();
max.push(CoworkerT(e.getA(), e.getD()));
min.pop();
}
return max;
}
// Driver code
int main()
{
int h, c, i, a, d;
cin >> h >> c;
// Creates a Min heap of points (order by possible a +d combination )
priority_queue <CoworkerT, vector<CoworkerT>, Min > pq;
// Creates a Max heap of points (order by actual a value )
priority_queue <CoworkerT, vector<CoworkerT>, Max > max;
// Insert points into the min heap
for (int i = 0; i < c; i++) {
a = AskForA();
d = AskForD();
pq.push(CoworkerT(a, d));
}
i = 0;
while (i < h) {
CoworkerT e = pq.top();
a = e.AddAD();
d = e.getD();
pq.pop();
pq.push(CoworkerT(a, d));
i++;
}
max = PopulateMax(max, pq);
CoworkerT eMax = max.top();
cout << eMax.getA() << endl;
return 0;
}
I just want to say that I ended up using something similar to my original algorithm using the heap. The problem was my use of int I switched to an unsigned long long int ~(though that might have been overkill?) and it worked like a charm.
// C++ program to use priority_queue to implement Min Heap
// for user defined class
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// User defined class, coworker
class CoworkerT {
private:
unsigned long long int a;
unsigned long long int d;
public:
CoworkerT(unsigned long long int _a, unsigned long long int _d){
a = _a;
d = _d;
}
unsigned long long int SimAddAD() const{
return a + d;
}
unsigned long long int AddAD(){
return a + d;;
}
unsigned long long int getA() const {
return a;
}
unsigned long long int getD() const {
return d;
}
};
//compare two coworkers possible a + d values
struct MinSort {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.SimAddAD() < p2.SimAddAD();
}
};
//compare two coworkers possible a + d values ~for some reason heap lesser than or greater need to be reverse of operator for sort???
struct Min {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.SimAddAD() > p2.SimAddAD();
}
};
//compare two a values between coworkers
struct MaxSort {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.getA() > p2.getA();
}
};
void FindAndPrintMax(vector<CoworkerT>& max) {
sort(max.begin(), max.end(), MaxSort());
CoworkerT minMax = max.front();
cout << minMax.getA();
}
void InputCoworkersAD(vector<CoworkerT>& min, unsigned long long int& h, unsigned long long int& c) {
int a, d, i;
cin >> h >> c;
// Insert a and d into the vector
if (h <= 100000 && h >= 1 && c <= 100000 && c >= 1) {
for (i = 0; i < c; i++) {
cin >> a >> d;
min.push_back(CoworkerT(a, d));
}
}
make_heap(min.begin(), min.end(), Min());
}
void AskForHelp(vector<CoworkerT>& min, unsigned long long int h) {
int i = 0;
while (i < h) {
push_heap(min.begin(), min.end(), Min());
CoworkerT e = min.front();
pop_heap(min.begin(), min.end(), Min());
min.pop_back();
min.push_back(CoworkerT(e.AddAD(), e.getD()));
i++;
}
}
// Driver code
int main()
{
unsigned long long int h, c;
vector<CoworkerT> min;
InputCoworkersAD(min, h, c);
AskForHelp(min, h);
FindAndPrintMax(min);
return 0;
}

How to use a class in another class in Arduino C++ (FastLED)?

I am working on an ledstip project for my room. I am using arduino to do this. For this project i want to use C++ so i can use OOP. After i got my ledstrips working I wanted to create a cluster class that used the strip class to control a specific piece of the LED strip. I can't get this to work. The compiler gives no errors and I see no change after using the function Desk.rgb(0,100,0);.
Here is my .h file
#include <FastLED.h>
template<class T>
class Cluster {
public:
T Strip;
int first;
int last;
Cluster(T Strip, int first, int last) {
this->Strip = Strip;
this->first = first;
this->last = last;
}
void rgb(int r, int g, int b){
Strip.rgb( r, g, b, first, last);
}
};
template<byte pin, int AmountOfLeds>
class Strip {
public:
CRGB leds[AmountOfLeds];
void setup() {
FastLED.addLeds<WS2812, pin, GRB>(leds, AmountOfLeds);
rgb(0, 0, 0);
}
//hole strip
void rgb(int r, int g, int b) {
for (int i = 0; i <= AmountOfLeds - 1; i++) {
this->leds[i] = CRGB(r, g, b);
}
FastLED.show();
}
//single led
void rgb(int i, int r, int g, int b) {
this->leds[i] = CRGB(r, g, b);
FastLED.show();
}
//range
void rgb(int r, int g, int b, int f, int l) {
for (int i = f; i <= l; i++) {
this->leds[i] = CRGB(r, g, b);
}
FastLED.show();
}
void hsv(int h, int s, int v) {
for (int i = 0; i <= AmountOfLeds; i++) {
this->leds[i] = CHSV(h, s, v);
}
FastLED.show();
}
void hsv(int i, int h, int s, int v) {
this->leds[i] = CHSV(h, s, v);
FastLED.show();
}
void hsv(int h, int s, int v, int f, int l) {
for (int i = f; i <= l; i++) {
this->leds[i] = CHSV(h, s, v);
}
FastLED.show();
}
void hsvWhiteBalance(int S, int V) { //S is yellowness, V is brightness
hsv(15, S, V);
}
void rainbow(float V) {
for (int i = 0; i <= AmountOfLeds; i++) {
leds[i] = CHSV( float(i) * (255 / float(AmountOfLeds)), 255, V);
}
FastLED.show();
}
void rainbow(float p, float V) {
for (int i = 0; i <= AmountOfLeds; i++) {
leds[i] = CHSV( float(i) * (255.0 / float(AmountOfLeds) * p), 255, V);
}
FastLED.show();
}
};
This is my .ino file:
#include "LedClasses.h"
Strip<5, 190> DTVC;
Cluster<Strip<5, 190>> Desk(DTVC, 1, 42);
void setup() {
Serial.begin(9600);
DTVC.setup();
DTVC.hsvWhiteBalance(153, 50);
Desk.rgb(0,100,0);
//DTVC.rgb(Desk, 0, 100, 0);
}
Thanks in advance.
Doesn't work, because in the Cluster constructor you take Strip class by copy. Then, in your example you have 2 instances of Stripe: one in the global context, and one inside the Cluster. You invoke Stripe::setup (which calls FastLED.addLeds) on the instance in the global context (registering the address of the Stripe::ledspublic field in the FastLED library), but later you call rgb on the instance that lives inside your Cluster and has different Stripe::leds field.
To fix it quickly (not very clean, though), you can redesign your constructor to accept a reference instead of copy:
class Cluster {
public:
T& strip;
int first;
int last;
Cluster(T& s, int f, int l): strip(s), first(f), last(l) {}
Alternatively, you can redesign your architecture a bit more, to not use the templates so much (you can play with constexpr arguments instead).

How to call a function with structure (C++)

My code is not working because I have a problem with the call of my two functions when I use a structure. I think I didn't call it correctly but I'm not sure if the problem is here or in the definition itself.
Here is my code:
#include <stdio.h>
#define NUM 3
struct student{
char name[20];
int kor;
int math;
int eng;
int sum;
double avg;
double avg2;
double k, m, e;
};
void average(student* st)
{
int i, sum = 0;
for(i=0;i<NUM;i++) {
st[i].sum= st[i].kor + st[i].math + st[i].eng;
st[i].avg= st[i].sum / NUM;
}
}
void average2(student* st)
{
int i, sum = 0;
double K, M, E;
for(i=0;i<NUM;i++) {
K+= st[i].kor;
M+= st[i].math;
E+= st[i].eng;
}
}
int main(void)
{
student stu[NUM]={{"Tom"},{"Jane"},{"Eddy"}} ;
int i;
int max;
double K, M, E;
printf("Input scores.\n");
for(i=0;i<NUM;i++)
{ printf("\n<%s>\n",stu[i].name);
printf("Korean:");
scanf("%d",&stu[i].kor);
printf("Math:");
scanf("%d",&stu[i].math);
printf("English:");
scanf("%d",&stu[i].eng);
}
printf("\nName\tKorean\tMath\tEnglish\tSum\tAverage\n");
average(stu);
for(i=0;i<NUM;i++)
printf("%s\t%d\t%d\t%d\t%d\t%.2f\n",stu[i].name,stu[i].kor,stu[i].math,stu[i].eng,stu[i].sum,stu[i].avg);
average2(stu);
printf("Average %.2lf\t%.2lf%.2lf\n", k/3, m/3, e/3);
}
Thank you in advance for your answers, Coco
for loops should have { and } to enclose more than one line in c++.
for(i=0;i<NUM;i++)
{
st[i].sum= st[i].kor + st[i].math + st[i].eng;
st[i].avg= st[i].sum / NUM;
}
Also in your function average2 it is not clear what you are exactly doing.
You are declaring same variable in main and average2 double K, M, E; so the function will take local variable only.
For your second printf here is the logic.,
for(i=0;i<NUM;i++) {
K+= st[i].kor;
M+= st[i].math;
E+= st[i].eng;
}
printf("Average %.2lf\t%.2lf%.2lf\n", K/3, M/3, E/3);

C++ push_back overwrites last vector element

Since I cannot answer my own question in 8 hours after asking, I'm posting my solution here.
Made some mistakes in the incoming channel number and number of the vector element. Setting the value of channel-1 instead of channel fixed to problem.
My new function is as follows:
void input(long inlet, t_symbol *s, long ac, t_atom *av){
// GET VARIABLES
long channel = atom_getlong(av);
double value = atom_getfloat(av + 1);
long v_size = v_chan.size();
if(channel && v_size < channel){
for(int i = v_size; i < channel; i++){
v_chan.push_back(n_chan);
}
v_chan[channel - 1].value = value;
}
else if(channel){
v_chan[channel - 1].value = value;
}
}
I've got a vector containing structs, which I like to push_back with a new, empty struct.
Example code:
struct channels{
double value;
// eventually more variables
};
vector<channels> v_chan;
channels n_chan;
void push(){
v_chan.push_back(n_chan);
}
The problem is, if my vector contains elements, push_back add an element, but also overwrites the last element.
For example, if my vector size is 1 and element 0 has a value of 0.2, after push_back my vector size is 2, but element 0 and 1 have a value of 0.
What am I doing wrong here?
Real Code: (MAX/MSP external, function input is called in Max)
#include <maxcpp6.h>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
struct bind{
string param;
double* value;
int track;
double base;
double multiplier;
};
struct channels{
double value;
vector<int> bind;
};
vector<channels> v_chan;
vector<bind> v_bind(19);
channels n_chan;
class rec : public MaxCpp6<rec> {
public:
rec(t_symbol * sym, long ac, t_atom * av) {
setupIO(1, 1); // inlets / outlets
}
~rec() {}
// methods:
//SET BIND FUNCTION
void setBind(long inlet, t_symbol *s, long ac, t_atom *av){
}
void output(long track, long type){
}
void input(long inlet, t_symbol *s, long ac, t_atom *av){
// GET VARIABLES
long channel = atom_getlong(av);
double value = atom_getfloat(av + 1);
long v_size = v_chan.size();
if(v_size <= channel){
v_chan.push_back(n_chan);
}
else{
v_chan[channel].value = value;
}
}
void dump(long inlet){
for(int i = 1; i <= v_chan.size(); i++){
post("%d %.2f", i, v_chan[i].value);
}
}
void clearTrackBinds(long inlet){
}
void reset(long inlet){
clearTrackBinds(0);
}
};
C74_EXPORT int main(void) {
// create a class with the given name:
rec::makeMaxClass("solar_receiver");
REGISTER_METHOD_GIMME(rec, input);
REGISTER_METHOD_GIMME(rec, setBind);
REGISTER_METHOD(rec, dump);
REGISTER_METHOD(rec, clearTrackBinds);
REGISTER_METHOD(rec, reset);
}

expected an identifier c++

I am trying to write a class and I finally got it to compile, but visual studio still shows there are errors (with a red line).
The problem is at (I wrote #problem here# around the places where visual studio draws a red line):
1. const priority_queue<int,vector<int>,greater<int> #># * CM::getHeavyHitters() {
2. return & #heavyHitters# ;
3. }
And it says:
"Error: expected an identifier" (at the first line)
"Error: identifier "heavyHitters" is undefined" (at the second line)
The first problem I don't understand at all. The second one I don't understand because heavyHitters is a a member of CM and I included CM.
BTW, I tried to build. It didn't fix the problem.
Thanks!!!
The whole code is here:
Count-Min Sketch.cpp
#include "Count-Min Sketch.h"
CM::CM(double eps, double del) {
}
void CM::update(int i, int long unsigned c) {
}
int long unsigned CM::point(int i) {
int min = count[0][calcHash(0,i)];
return min;
}
const priority_queue<int,vector<int>,greater<int>>* CM::getHeavyHitters() {
return &heavyHitters;
}
CM::CM(const CM &) {
}
CM::~CM() {
}
int CM::calcHash(int hashNum, int inpt) {
int a = hashFunc[hashNum][0];
int b = hashFunc[hashNum][1];
return ((a*inpt+b) %p) %w;
}
bool CM::isPrime(int a) {
bool boo = true;
return boo;
}
int CM::gePrime(int n) {
int ge = 2;
return ge;
}
Count-Min Sketch.h
#pragma once
#ifndef _CM_H
#define _CM_H
using namespace std;
#include <queue>
class CM {
private:
// d = ceiling(log(3,1/del)), w = ceiling(3/eps)
int d,w,p;
// [d][w]
int long unsigned *(*count);
// [d][2]
int *(hashFunc[2]);
// initialized to 0. norm = sum(ci)
int long unsigned norm;
// Min heap
priority_queue<int,vector<int>,greater<int>> heavyHitters;
// ((ax+b)mod p)mod w
int calcHash(int hashNum, int inpt);
// Is a a prime number
bool isPrime(int a);
// Find a prime >= n
int gePrime(int n);
public:
// Constructor
CM(double eps, double del);
// count[j,hj(i)]+=c for 0<=j<d, norm+=c, heap update & check
void update(int i, int long unsigned c);
// Point query ai = minjcount[j,hj(i)]
int long unsigned point(int i);
const priority_queue<int,vector<int>,greater<int>>* getHeavyHitters();
// Copy constructor
CM(const CM &);
// Destructor
~CM();
};
#endif // _CM_H
>> is a single token, the right-shift (or extraction) operator. Some compilers don't recognize it correctly in nested template specialization. You have to put a space between the two angle brackets like this:
Type<specType<nestedSpecType> > ident;
^^^