1
- // Runtime: 1534 ms (Top 45.54%) | Memory: 199 MB (Top 25.74%)
2
1
class Solution {
2
+ vector<int > st;
3
3
public:
4
- map<pair<int , int >, int >edgeCount;
5
- vector<int >degree;
6
-
7
- vector<int > countPairsHelper (vector<int >&indegree, vector<int >&queries, int n){
8
- vector<int >ans;
9
-
10
- // for each query, time: O(2*n) for two pointer and O(uniqueEdgesCount)
11
- for (int query: queries){
12
- // two pointer
13
- int i = 0 , j = n-1 , total = 0 ;
14
- while (i != j){
15
- if (degree[i] + degree[j] > query){
16
- j--;
17
- }
18
- else {
19
- total += (n-j-1 );
20
- i++;
21
- }
22
- }
23
- while (i < n){
24
- total += (n-i-1 );
25
- i++;
26
- }
27
-
28
- // remove the negative contribution of edgeCount from all the pairs so far counted
29
- for (auto i: edgeCount){
30
- int u = i.first .first , v = i.first .second , w = i.second ;
31
- // cout<<indegree[u] + indegree[v] - w<<endl;
32
- if (indegree[u] + indegree[v] > query && indegree[u] + indegree[v] - w <= query){
33
- total -= 1 ;
34
- }
35
- }
36
- ans.push_back (total);
4
+ void update (int tind,int tl,int tr,int ind,int val){
5
+ if (tl>tr)
6
+ return ;
7
+ if (tl==tr){
8
+ st[tind]+=val;
9
+ return ;
37
10
}
38
- return ans;
11
+ int tm =tl+((tr-tl)>>1 ),left=tind<<1 ;
12
+ if (ind<=tm )
13
+ update (left,tl,tm ,ind,val);
14
+ else
15
+ update (left|1 ,tm +1 ,tr,ind,val);
16
+ st[tind]=st[left]+st[left|1 ];
39
17
}
40
- vector<int > countPairs (int n, vector<vector<int >>& edges, vector<int >& queries) {
41
-
42
- vector<int >indegree (n, 0 );
43
- for (auto edge: edges){
44
- int x = edge[0 ], y = edge[1 ];
45
- int u = min (x,y);
46
- int v = max (x,y);
47
- --u, --v;
48
- edgeCount[{u,v}] += 1 ;
49
- indegree[u]++;
50
- indegree[v]++;
18
+
19
+ int query (int tind,int tl,int tr,int ql,int qr){
20
+ if (tl>tr or qr<tl or ql>tr)
21
+ return 0 ;
22
+ if (ql<=tl and tr<=qr)
23
+ return st[tind];
24
+ int tm =tl+((tr-tl)>>1 ),left=tind<<1 ;
25
+ return query (left,tl,tm ,ql,qr)+query (left|1 ,tm +1 ,tr,ql,qr);
26
+ }
27
+
28
+ vector<int > countPairs (int n,vector<vector<int >>& a,vector<int >& q) {
29
+ vector<int > f (n+2 ,0 );
30
+ vector<unordered_map<int ,int >> mp (n+2 ); // using a normal map gives TLE
31
+
32
+ for (auto v:a){
33
+ int mx=max (v[0 ],v[1 ]),mn=min (v[1 ],v[0 ]);
34
+ f[mx]++;
35
+ f[mn]++;
36
+ mp[mx][mn]++;
51
37
}
52
-
53
- for (int i = 0 ; i < n; ++i){
54
- degree.push_back (indegree[i]);
38
+
39
+ vector<int > ans (q.size (),0 );
40
+ int m=a.size ();
41
+ st.resize (4 *m+40 ,0 );
42
+
43
+ for (int i=n;i;i--){
44
+ // reducing the common edges between current node and its adjacent
45
+ for (auto e:mp[i]){
46
+ update (1 ,0 ,m,f[e.first ],-1 );
47
+ update (1 ,0 ,m,f[e.first ]-e.second ,1 );
48
+ }
49
+
50
+ int curr=f[i];
51
+ for (int j=0 ;j<q.size ();j++)
52
+ ans[j]+=query (1 ,0 ,m,max (0 ,q[j]-curr+1 ),m);
53
+
54
+ // reversing the changes made initially
55
+ for (auto e:mp[i]){
56
+ update (1 ,0 ,m,f[e.first ],1 );
57
+ update (1 ,0 ,m,f[e.first ]-e.second ,-1 );
58
+ }
59
+
60
+ update (1 ,0 ,m,f[i],1 );
55
61
}
56
- sort (degree.begin (), degree.end ()); // sort degree to apply smart two pointer
57
- return countPairsHelper (indegree, queries, n);
62
+ return ans;
58
63
}
59
64
};
0 commit comments