#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(non_upper_case_globals)]


macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let mut s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($next:expr, [$t:tt]) => {
        {
            let len = read_value!($next, usize);
            (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
        }
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}


#[cfg(debug_assertions)]
macro_rules! mydbg {
    //($arg:expr) => (dbg!($arg))
    ($arg:expr) => (println!("{:?}",$arg));
}


#[cfg(not(debug_assertions))]
macro_rules! mydbg {
    ($($arg:expr),*) => {};
}


use std::cmp;
use std::collections::HashMap;
use std::cell::RefCell;



pub struct UnionFind{
    parent : Vec<i32>,
}

impl UnionFind{
    pub fn new(n : usize) -> Self{
        UnionFind{
            parent  :vec![-1;n],
        }
    }

    pub fn root (&mut self , a : i32) -> i32{
        if self.parent[a as usize] < 0 {
            return a;
        }
        else{
            let index = self.parent[a as usize];
            self.parent[a as usize] = self.root(index);
            return self.parent[a as usize];
        }
    }

    pub fn rank  (&mut self , a : i32) -> i32{
        let tmp = self.root(a);
        return -1 * self.parent[tmp as usize];
    }

    pub fn ranks (&mut self, ret : &mut Vec<i32>)->bool{
        for item in self.parent.iter().filter(|&x| {*x<0}){
            ret.push(item.clone());
        }
        return true;
        
    }
    pub fn join(&mut self , a: i32 , b : i32)->bool{

        
        let mut a_root = self.root(a); 
        let mut b_root = self.root(b);
        if(a_root == b_root) {return false;} 


        if(self.rank(b_root) > self.rank(a_root)){
            std::mem::swap(&mut a_root,&mut b_root);
        }

        self.parent[a_root as usize] +=  self.parent[b_root as usize]; //AのルートにBの要素数を加える
        self.parent[b_root as usize] = a_root; //Bの親をAに変更
        return true;
    }

    pub fn fuben (&mut  self)->i64{
        let mut ret = 0_i64;        
        for item in self.parent.iter(){
            if(*item < -1){
                ret += (*item * (*item+1)) as i64;
            }
        }
        return ret;
    }




}



fn main() {

    input! { 
       n: usize,
       m: usize,
       bridge : [(i32,i32);m],
    }

    let mut ans = vec![];
    let mut bridge = bridge.into_iter().map(|(x,y)|{
        (x-1,y-1)
    }).collect::<Vec<_>>();
    bridge.reverse();
   
   

    let mut fuben = vec![0_i64;n];
    
    let goukei = (n*(n-1))as i64;
    ans.push(goukei);
    let mut ufind = UnionFind::new(n);
    for &(a,b) in &bridge{
        let a_root =  ufind.root(a) as usize;
        let b_root = ufind.root(b) as usize;
        let joinret = ufind.join(a, b);
        if(joinret == true){
        let a_root_new =  ufind.root(a) as usize;
            //ans.push((goukei-ufind.fuben())/2);
            let a_fuben = ufind.rank(a_root_new as i32) as i64;

            
            
            let mut ret = ans[ans.len()-1];
            let tmp = fuben[a_root] + fuben[b_root];
            let tmp2 = a_fuben*(a_fuben-1);
            ret = ret + tmp - tmp2; 
            fuben[a_root as usize] = 0;
            fuben[b_root as usize] = 0;
            fuben[a_root_new as usize] = tmp2;
            ans.push(ret);
        }
        else{
            let tmp = ans[ans.len()-1];
            ans.push(tmp);
        }

    }

    ans.pop();
    ans.reverse();

    
    
    for item in &ans{
        println!("{}",item/2);
    }
    


}


Measured memory_bytes: 11516