题面:
思路:
这道题乍一看有点难
但是实际上研究一番以后会发现,对于每一个位置只会有一个数要去那里,还有一个数要离开
那么只要把每个数和他将要去的那个位置连起来,构成了一个每个点只有一个入边一个出边的一张图
那么在这张图里的一个环,就代表着一个满足条件的子序列
所以只要把图建出来以后,统计图中的每一个环就可以了
Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 inline int read(){ 8 int re=0,flag=1;char ch=getchar(); 9 while(ch>‘9‘||ch<‘0‘){ 10 if(ch==‘-‘) flag=-1; 11 ch=getchar(); 12 } 13 while(ch>=‘0‘&&ch<=‘9‘) re=(re<<1)+(re<<3)+ch-‘0‘,ch=getchar(); 14 return re*flag; 15 } 16 int n,first[100010],cnt,tot; 17 bool vis[100010]; 18 struct edge{ 19 int to,next; 20 }a[200010]; 21 struct node{ 22 int val,num; 23 }x[100010]; 24 priority_queue<int,vector<int>,greater<int> >q[100010]; 25 bool cmp(node l,node r){ 26 return l.val<r.val; 27 } 28 inline void add(int u,int v){ 29 // cout<<u<<ends<<v<<endl; 30 a[++cnt]=(edge){v,first[u]};first[u]=cnt; 31 } 32 void dfs(int u,int now){ 33 // cout<<"dfs "<<u<<ends<<now<<endl; 34 vis[u]=1;q[now].push(u); 35 int i,v; 36 for(i=first[u];~i;i=a[i].next){ 37 v=a[i].to; 38 if(vis[v]) return; 39 dfs(v,now); 40 } 41 } 42 int main(){ 43 memset(first,-1,sizeof(first)); 44 int i,j; 45 n=read(); 46 for(i=1;i<=n;i++){ 47 x[i].val=read();x[i].num=i; 48 } 49 sort(x+1,x+n+1,cmp); 50 for(i=1;i<=n;i++){ 51 add(i,x[i].num); 52 } 53 for(i=1;i<=n;i++){ 54 if(!vis[i]) dfs(i,++tot); 55 } 56 printf("%d\n",tot); 57 for(i=1;i<=tot;i++){ 58 printf("%d",q[i].size()); 59 while(!q[i].empty()) printf(" %d",q[i].top()),q[i].pop(); 60 printf("\n"); 61 } 62 }