QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#865428 | #9731. Fuzzy Ranking | surenjamts# | WA | 29ms | 3712kb | C++20 | 6.3kb | 2025-01-21 18:28:38 | 2025-01-21 18:28:38 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
// Utility macros/functions
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define put(x) cout << (x) << '\n'
// Kosaraju components
void dfs1(int node, vector<vector<int>>& adj, vector<bool>& visited, stack<int>& finishOrder) {
visited[node] = true;
for (int neighbor : adj[node]) {
if (!visited[neighbor]) {
dfs1(neighbor, adj, visited, finishOrder);
}
}
finishOrder.push(node);
}
void dfs2(int node, vector<vector<int>>& radj, vector<bool>& visited, vector<int>& component) {
visited[node] = true;
component.push_back(node);
for (int neighbor : radj[node]) {
if (!visited[neighbor]) {
dfs2(neighbor, radj, visited, component);
}
}
}
vector<vector<int>> kosaraju(int n, vector<vector<int>>& edges) {
// 1) Build adjacency
vector<vector<int>> adj(n);
for (auto &e : edges) {
adj[e[0]].push_back(e[1]);
}
// 2) DFS on original graph to get finishing order
vector<bool> visited(n, false);
stack<int> finishOrder;
for (int i = 0; i < n; i++){
if(!visited[i]) dfs1(i, adj, visited, finishOrder);
}
// 3) Reverse graph
vector<vector<int>> radj(n);
for (auto &e : edges){
radj[e[1]].push_back(e[0]);
}
// 4) DFS on reversed graph using finish order
fill(visited.begin(), visited.end(), false);
vector<vector<int>> scc;
while(!finishOrder.empty()){
int node = finishOrder.top();
finishOrder.pop();
if(!visited[node]){
vector<int> component;
dfs2(node, radj, visited, component);
scc.push_back(component);
}
}
return scc;
}
void solve() {
int n, k, q;
cin >> n >> k >> q;
// Read all edges from k lists of size n
vector<vector<int>> edges;
edges.reserve(k * (n - 1)); // optional optimization
// Read k permutations, zero-based
vector<vector<int>> lists(k, vector<int>(n));
for (int i = 0; i < k; i++) {
for (int j = 0; j < n; j++) {
cin >> lists[i][j];
lists[i][j]--;
if(j > 0) {
edges.push_back({lists[i][j - 1], lists[i][j]});
}
}
}
// Kosaraju -> component IDs
auto comps = kosaraju(n, edges);
vector<int> compID(n);
for (int i = 0; i < (int)comps.size(); i++) {
for (int v : comps[i]) {
compID[v] = i + 1; // 1-based
}
}
// Build 'ends[i]' and 'p[i]' for each of the k lists
// 'ends[i]' = boundaries where compID changes
// 'p[i]' = partial sum array of something (the sum of intervals, presumably)
vector<vector<int>> ends(k), p(k, vector<int>(n, 0));
for (int i = 0; i < k; i++) {
ll sum = 0;
int startIdx = 0; // start of the current interval
int prevComp = compID[lists[i][0]];
for (int j = 1; j < n; j++) {
int curComp = compID[lists[i][j]];
// If compID changes, we close off the interval [startIdx..j-1]
if (curComp != prevComp) {
ll len = j - startIdx; // length of this interval
// sum of pairs: len*(len-1)/2
sum += len * (len - 1) / 2;
p[i][j-1] = sum; // store partial sum up to j-1
ends[i].push_back(j-1);
startIdx = j; // start new interval
prevComp = curComp;
}
}
// Close off final interval [startIdx..n-1]
ll lastLen = n - startIdx;
sum += lastLen * (lastLen - 1) / 2;
p[i][n - 1] = sum;
ends[i].push_back(n - 1);
}
// Process queries
ll prevAns = 0;
while (q--) {
ll id, l, r;
cin >> id >> l >> r;
// decode with previous answer
id = (id + prevAns) % k;
l = (l + prevAns) % n;
r = (r + prevAns) % n;
// If they're in the same SCC, easy
if (compID[l] == compID[r]) {
ll length = (r - l + 1);
// If r >= l, length is (r-l+1). If r < l, do you wrap or is it invalid?
// For now, assume r >= l from the problem statement.
ll ans = length * (length - 1) / 2;
cout << ans << "\n";
prevAns = ans;
continue;
}
// Otherwise, we do partial sums:
ll ans = 0;
// --- Compute L boundary:
auto itL = std::lower_bound(ends[id].begin(), ends[id].end(), l);
ll L;
if (itL == ends[id].end()) {
// l is bigger than any boundary => use the last boundary
L = ends[id].back();
} else {
L = *itL;
}
// --- Compute R boundary:
auto itR = std::lower_bound(ends[id].begin(), ends[id].end(), r);
ll R;
if (itR == ends[id].begin()) {
// r <= ends[id].front()
R = ends[id].front();
} else {
// Move one step back
--itR;
R = *itR;
}
// Interval piece from [l..L]
// sum of pairs = (len*(len-1))/2
ll lenLeft = (L >= l) ? (L - l + 1) : 0;
ans += lenLeft * (lenLeft - 1) / 2;
// Interval piece from [R..r]
ll lenRight = (r > R) ? (r - R) : 0;
ans += lenRight * (lenRight - 1) / 2;
// The middle portion is p[id][R] - p[id][L], but only if R >= L
// If R < L, that means there's no actual "middle" to add.
if (R >= L) {
ans += p[id][R] - ((L < 0) ? 0 : p[id][L]);
// Because p[id][x] is a partial sum "up to index x."
// If you originally stored partial sums differently, adjust accordingly.
// In your code, you're using p[id][R] - p[id][L], but that might not handle L=0 properly.
}
// cout << L << ' ' << R << endl;
//cout << lenLeft << ' ' << lenRight << endl;
cout << ans << "\n";
prevAns = ans;
}
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t--){
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3712kb
input:
2 5 2 2 1 2 3 4 5 5 4 3 2 1 1 0 2 1 2 1 5 3 3 1 2 3 4 5 1 3 2 4 5 1 2 3 5 4 0 0 2 0 2 3 1 0 3
output:
3 10 1 1 2
result:
ok 5 lines
Test #2:
score: -100
Wrong Answer
time: 29ms
memory: 3712kb
input:
2000 10 10 10 4 5 3 6 8 9 2 1 7 10 4 5 6 3 8 9 1 2 10 7 5 4 3 6 8 9 1 2 7 10 4 5 6 3 8 9 1 2 7 10 4 5 3 6 8 9 2 1 10 7 4 5 6 3 8 9 1 2 10 7 5 4 6 3 8 9 1 2 7 10 5 4 6 3 8 9 1 2 10 7 4 5 6 3 8 9 2 1 7 10 5 4 3 6 8 9 2 1 10 7 3 1 6 5 7 8 0 2 3 7 9 9 2 1 9 6 1 6 7 2 3 0 0 4 1 8 1 1 8 7 10 10 10 9 10 5 ...
output:
1 2 0 0 3 2 0 2 2 4 4 0 1 4 0 1 2 4 4 3 1 6 28 0 0 10 10 6 6 15 0 3 15 15 18 3 1 1 6 13 1 12 4 1 6 2 1 3 4 1 1 3 2 4 0 3 4 4 4 4 0 0 1 1 2 0 0 1 2 1 1 0 0 3 0 0 0 4 4 1 3 6 16 16 0 11 16 1 4 21 2 3 3 0 1 1 1 2 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 28 3 0 3 4 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 1 3 1 0 0 3 21 9 4 ...
result:
wrong answer 2nd lines differ - expected: '1', found: '2'