1 //Result:2012-08-12 13:44:40 Accepted 4351 812MS 11016K 3495 B C++ Wizmann 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <algorithm> 7 8 using namespace std; 9 10 #define print(x) cout<<x<<endl 11 #define input(x) cin>>x 12 #define SIZE 100100 13 #define FORCE 1024 14 15 inline int left(int x){return (x<<1)+1;} 16 inline int right(int x){return (x<<1)+2;} 17 18 struct node 19 { 20 int l,r,val; 21 int now,lson,rson; 22 node(){} 23 node(int il,int ir) 24 { 25 l=il;r=ir; 26 val=now=lson=rson=0; 27 } 28 inline void init(int ival) 29 { 30 val=now=lson=rson=(1<<ival); 31 } 32 inline int getmid(){return (l+r)>>1;} 33 inline int equal(int il,int ir){return l==il&&r==ir;} 34 inline int has_next(){return l!=r;} 35 }; 36 37 struct result 38 { 39 int val,now,lson,rson; 40 result(){} 41 result(int ival,int inow,int ilson,int irson) 42 { 43 val=ival; 44 now=inow; 45 lson=ilson; 46 rson=irson; 47 } 48 }; 49 50 node stree[SIZE*3]; 51 int n; 52 int k[SIZE]; 53 int mp[FORCE+10][FORCE+10]; 54 const int ROOT=0; 55 56 void init() 57 { 58 for(int i=0;i<FORCE;i++) 59 { 60 for(int j=0;j<FORCE;j++) 61 { 62 for(int a=0;a<=9;a++) if(i&(1<<a)) 63 { 64 for(int b=0;b<=9;b++) if(j&(1<<b)) 65 { 66 int val=(a+b-1)%9+1; 67 mp[i][j]|=(1<<val); 68 } 69 } 70 } 71 } 72 } 73 74 void stree_init(int l,int r,int pos=ROOT) 75 { 76 stree[pos]=node(l,r); 77 if(l==r) stree[pos].init(k[l]); 78 else if(l<r) 79 { 80 int mid=(l+r)>>1; 81 stree_init(l,mid,left(pos)); 82 stree_init(mid+1,r,right(pos)); 83 84 stree[pos].val=mp[stree[left(pos)].val][stree[right(pos)].val]; 85 stree[pos].lson=stree[left(pos)].lson \ 86 | mp[stree[left(pos)].val][stree[right(pos)].lson]; 87 stree[pos].rson=stree[right(pos)].rson \ 88 | mp[stree[right(pos)].val][stree[left(pos)].rson]; 89 stree[pos].now=stree[left(pos)].now \ 90 | stree[right(pos)].now \ 91 | mp[stree[left(pos)].rson][stree[right(pos)].lson]; 92 } 93 } 94 95 result stree_query(int l,int r,int pos=ROOT) 96 { 97 if(stree[pos].equal(l,r)) 98 { 99 return result(stree[pos].val,stree[pos].now,stree[pos].lson,stree[pos].rson); 100 } 101 else 102 { 103 int mid=stree[pos].getmid(); 104 if(r<=mid) return stree_query(l,r,left(pos)); 105 else if(l>mid) return stree_query(l,r,right(pos)); 106 else 107 { 108 result a=stree_query(l,mid,left(pos)); 109 result b=stree_query(mid+1,r,right(pos)); 110 111 int val=mp[a.val][b.val]; 112 //val代表[l,r]区间的DigitalRoot 113 //mp[a.val][b.val],由于a.val和b.val都只有一个"1"位,所以mp[a.val][b.val]==DigitalRoot(a+b),也只有一位 114 int lson=a.lson | mp[a.val][b.lson]; 115 //lson是指[l,r]区间的前辍,由a(左边)的lson与a.val与b.lson的和组成 116 int rson=b.rson | mp[a.rson][b.val]; 117 //同上 118 int now = a.now | b.now | mp[a.rson][b.lson]; 119 //now代表当前区间能表示的DigitalRoot的种类数 120 //a.now | b.now 父节点是继承子节点的可行值(这个好理解) 121 //mp[a.rson][b.lson]是指在[l,r]的中点mid处,[...mid][mid...]这种类型的合并 122 123 return result(val,now,lson,rson); 124 } 125 } 126 } 127 128 129 int main() 130 { 131 132 int T,a,b,q; 133 input(T); 134 init(); 135 int res[10]; 136 int cas=1; 137 while(T--) 138 { 139 printf("Case #%d:\n",cas++); 140 input(n); 141 for(int i=1;i<=n;i++) 142 { 143 scanf("%d",&a); 144 k[i]=(a-1)%9+1; 145 } 146 stree_init(1,n); 147 input(q); 148 while(q--) 149 { 150 scanf("%d%d",&a,&b); 151 result r=stree_query(a,b); 152 int ptr=0,val=9; 153 memset(res,-1,sizeof(res)); 154 while(ptr<5 && val>=0) 155 { 156 if(r.now & (1<<val)) 157 { 158 res[ptr++]=val; 159 } 160 val--; 161 } 162 for(int i=0;i<5;i++) 163 { 164 if(i) printf(" "); 165 printf("%d",res[i]); 166 } 167 puts(""); 168 } 169 if(T) puts(""); 170 } 171 return 0; 172 }