题解:先把m次操作的置换给求出来,记住每个点在该置换中的位置,长度不同的置换最多有sqrt(n)个数,这里我自己只开了300个(够用)。然后对每个询问按%m分类,然后对每个%m类 求出每个点贡献,再统计答案。
#include"bits/stdc++.h"
using namespace std;
const int MX = 1e5+7;
int n,m,q;
int res[MX][300];
int ex[MX],ex2[MX];
int l[11],r[11];
int ans[MX];
int len[MX],blo[MX],pos[MX],col,maxl;
vector<int> G[MX];
struct node{
int k,id;
node(){}
node(int k, int id) : k(k), id(id){}
};
vector<node> rem[11];
vector<int> Len;
map<int,int> mp;
bool vis[MX];
bool check(int *a, int *b)
{
for(int i = 1; i <= n; i++)
if(a[i] != b[i]) return 0;
return 1;
}
void work(int mm)
{
for(int i = 0; i <= maxl; i++)
for(int j = 0; j < Len.size(); j++)
res[i][j] = 0;
for(int i = 1; i <= col; i++) {
int sz = G[i].size();
for(int j = 0; j < sz; j++) {
int x = G[i][j], y = ex2[x], le = len[blo[x]];
if(blo[x] != blo[y]) continue;
int p = pos[x] - pos[y];
if(p < 0) p += le;
res[p][mp[le]]++;
}
}
for(int i = 0; i < rem[mm].size(); i++) {
int k = rem[mm][i].k, id = rem[mm][i].id;
int ret = 0;
for(int j = 0; j < Len.size(); j++) {
int lx = Len[j];
ret += res[(k/m)%lx][j];
}
ans[id] = ret;
}
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
while(~scanf("%d%d%d",&n,&m,&q)) {
assert(n >= 1 && n <= 100000 && m >= 1 && m <= 10 && q >= 1 && q <= 100000);
mp.clear(); Len.clear();
for(int i = 1; i <= n; i++) {
ex2[i] = ex[i] = i;
G[i].clear();
vis[i] = 0;
}
for(int j = 1; j <= m; j++) {
scanf("%d%d",&l[j],&r[j]);
}
for(int i = 1; i <= m; i++) {
for(int j = l[i], l = r[i]; j < l; j++, l--) {
swap(ex[j],ex[l]);
}
}
int tyl = 0;
maxl = col = 0;
for(int i = 1; i <= n; i++) {
int x = i, l = 0;
if(vis[x]) continue;
++col;
while(!vis[x]) {
++l;
vis[x] = 1;
blo[x] = col;
pos[x] = l - 1;
G[col].push_back(x);
x = ex[x];
}
if(!mp.count(l)) {
mp[l] = tyl++;
Len.push_back(l);
}
len[blo[x]] = l;
maxl = max(maxl,l);
}
for(int i = 1,k; i <= q; i++) {
scanf("%d",&k);
int re = k%m;
rem[re].push_back(node(k,i));
}
for(int i = 0; i < m; i++) {
work(i);
rem[i].clear();
for(int j = l[i+1], l = r[i+1]; j < l; j++,l--){
swap(ex2[j],ex2[l]);
}
}
for(int i = 1; i <= q; i++)
printf("%d\n",ans[i]);
}
return 0;
}