13 analog solution to a problem

A. Matrix Games

40% by partial minutes ago, we found that the complexity of the program can not be $ O (nk) $.

Provided $ h (i) $ $ I $ row represents the final total multiplication factor, $ l (i) $ $ I $ denotes the column.

Consider each point $ (i, j) $, its contribution to the final answer is $ ((i-1) * m + j) * h (i) * l (j) $.

Found can be split into $ (i-1) * m * h (i) * l (j) + j * l (j) * h (i) $.

Maintenance Total $ l (j), l (j) * j $ and $ I $ enumeration to $ O (n + m) $ solution.

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 const int N=1000100;
 7 const int mod=1e9+7;
 8 int n,m,k,x,y;
 9 char opt;
10 ll h[N],l[N],sum,sumj;
11 int main(){
12     scanf("%d%d%d",&n,&m,&k);
13     for(int i=1;i<=n;++i) h[i]=1;
14     for(int i=1;i<=m;++i) l[i]=1;
15     while(k--){
16         scanf(" %c%d%d",&opt,&x,&y);
17         if(opt=='R') h[x]=h[x]*y%mod;
18         else l[x]=l[x]*y%mod;
19     }
20     ll ans=0;
21     for(int i=1;i<=m;++i) sum=(sum+l[i])%mod,sumj=(sumj+l[i]*i)%mod;
22     for(int i=1;i<=n;++i) ans=(ans+(1ll*(i-1)*m%mod*sum%mod+sumj)*h[i])%mod;
23     printf("%lld\n",ans);
24     return 0;
25 }
View Code

 

 

 

 

 

 

B. Hopscotch

Thinking positive solutions that block thinking:

Starting from any point in the matrix, there must be no longer than $ n * m $ loop section.

Thought of a block, a length of $ m $ into a block.

In other words, we maintain the first $ 1, column $ i $ $ $ m $-step walk, which will return to the line, and this is set to $ jump (i) $.

$ Jump (i) $ there must be no longer than n-$ $ loop section.

Thus a simple query, first come first column violence, then go $ $ Jump loop section, directly on the circular section of the length of the modulus,

Walk the rest of the $ jump $, you can take the violence.

But to get more difficult to modify.

 

Another idea is to maintain the tree line mapping, in fact, using a multiplier of ideas:

Building an index interval $ m $ segment tree, each node of the tree to create a mapping array $ map $.

Mapping array size is $ n $, where the node $ [l, r] $ map $ on (I) represents $ I $ $ $ L row away from $ $ r-l number of rows reaches step 1 $ +.

Apparently replacement is is associative, which means it can be quickly power.

For the modification operation, directly modify the line replacement tree leaf node, and then upload the replacement.

For inquiry operations, the number of steps is set $ k $.

Queries go permutation $ m $ steps, the $ \ lfloor \ frac {k} {m} \ rfloor * m $ is part of the direct power of fast,

$ K $ $ mod $ $ m $ portion to violence.

Complexity $ O (qnlogm) $.

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=2015;
 6 int n,m,q,xn=1,yn=1,a[N][N],jump[N];
 7 struct map{
 8     int mp[N];
 9     void init(){
10         for(int i=1;i<=n;++i) mp[i]=i;
11     }
12 }ans,tmp,as;
13 void mult(const map &a,const map &b,map *x){
14     for(register int i=1;i<=n;++i) tmp.mp[i]=b.mp[a.mp[i]];
15     memcpy(x,&tmp,sizeof(map));
16 }
17 void qpow(map &base,int k,map *x){
18     as.init();
19     while(k){
20         if(k&1) mult(as,base,&as);
21         mult(base,base,&base);
22         k>>=1;
23     }
24     memcpy(x,&as,sizeof(map));
25 }
26 struct node{
27     int l,r;
28     node *lch,*rch;
29     map s;
30 }pool[N<<1],*ptr=pool,*root;
31 inline int get(int x,int y){
32     y=(y==m?1:y+1);
33     if(a[x][y]>a[x-1?x-1:n][y]&&a[x][y]>a[x+1<=n?x+1:1][y]) return x;
34     if(a[x-1?x-1:n][y]>a[x][y]&&a[x-1?x-1:n][y]>a[x+1<=n?x+1:1][y]) return x-1?x-1:n;
35     return x+1<=n?x+1:1;
36 }
37 void build(node *&p,int l,int r){
38     p=new(ptr++) node();
39     p->l=l; p->r=r;
40     if(l==r){
41         for(register int i=1;i<=n;++i) p->s.mp[i]=get(i,l);
42         return ;
43     }
44     int mid=l+r>>1;
45     build(p->lch,l,mid);
46     build(p->rch,mid+1,r);
47     mult(p->lch->s,p->rch->s,&p->s);
48 }
49 void query(node *p,int l,int r,map *ans){
50     if(p->l>=l&&p->r<=r){
51         mult(*ans,p->s,ans);
52         return ;
53     }
54     if(l<=p->lch->r) query(p->lch,l,r,ans);
55     if(r>=p->rch->l) query(p->rch,l,r,ans);
56 }
57 void change(node *p,int pos){
58     if(p->l==p->r){
59         for(register int i=1;i<=n;++i) p->s.mp[i]=get(i,pos);
60         return ;
61     }
62     if(pos<=p->lch->r) change(p->lch,pos);
63     else change(p->rch,pos);
64     mult(p->lch->s,p->rch->s,&p->s);
65 }
66 inline int read(register int x=0,register char ch=getchar()){
67     while(!isdigit(ch)) ch=getchar();
68     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
69     return x;
70 }
71 int main(){
72     n=read(); m=read();
73     for(register int i=1;i<=n;++i) for(register int j=1;j<=m;++j) a[i][j]=read();
74     build(root,1,m);
75     q=read();
76     char opt;
77     for(register int i=1,x,y,k;i<=q;++i){
78         do opt=getchar();
79         while(opt!='m'&&opt!='c');
80         if(opt=='m'){
81             k=read(); ans.init();
82             query(root,yn,m,&ans); if(yn-1) query(root,1,yn-1,&ans);
83             qpow(ans,k/m,&ans); k%=m;
84              if (k) {
 85                  if (in k + 1 <= m) query (root, in, in + k- 1 , & ans);
86                  else query (root, in, m, & ans), query (root, 1 , k-m + zoom 1 , & ans);
87              }
 88              printf ( " % d% d \ n " , x n = ans.mp [xn], in = (In + k 1 )% m + 1 );
89          }
 90          else {
 91              x = read (); y = read (); k = read ();
92              a [x] [y] = k;
93             change(root,y-1?y-1:m);
94         }
95     }
96     return 0;
97 }
View Code

 

 

 

 

 

 

C. graceful sequence

Easy to think of one pair each inquiry Online $ O (n) $ algorithm to solve.

Set interval $ (l, r) $, $ (l, r) the minimum and maximum weights in the range $ $ (vl, vr) $.

If $ vr-vl! = Rl $, the current range is not a beautiful sequence.

If the maximum value of $ vl $, $ vr $ are present in the beautiful sequence, then all the numbers between the two should appear.

Because beautiful sequence is continuous, and only one position for each number,

All the numbers between the two appear equivalent to the number of all the positions between the position of the leftmost and rightmost value value appears.

However, this is the case most value $ vl $, $ vr $ may change.

So the cycle continues constantly, until the end of a beautiful sequence conditions are met.

 

This algorithm has been found to be good enough in the random data, can solve the problem within 1s of the.

However, it will be specially constructed data card into a real $ O (n) $.

For example, a simple data, 2,513,746.

Manual simulation, when the interrogation interval $ (3,4) $, the need to loop n times to get results.

So this algorithm is specially constructed data card out, and the next block is the idea of ​​an optimization algorithm:

Set interval interval containing $ A $ $ B $, so easy to prove that range $ A $ answer section with a constant interval containing $ B $ answers range.

Range $ B $ answer, you can directly update the range $ A $.

So also a problem to be solved is how to find the appropriate update interval based on current range.

Practice block. The 1 ~ n $ k $ divided into blocks, each block size is $ Q $,

About endpoint enumeration blocks, a total of $ k ^ 2 $ times, the answer to calculate a contiguous block.

In the course of the cycle, and continue to find the largest contiguous block contained, you can try to update the answer.

然而我觉得这个算法的复杂度仍然是$O(qn)$的,不过它成功过掉了出题人构造的数据。

 

 1 #include<cstdio>
 2 #include<cmath>
 3 const int N=100100;
 4 int n,m,a[N],pos[N],mnd[20][N],mxd[20][N],mnp[20][N],mxp[20][N],pw[N],q;
 5 int lf[550][550],rf[550][550],bl[N];
 6 #define max(a,b) (a>b?a:b)
 7 #define min(a,b) (a<b?a:b)
 8 #define askmxp(l,r) max(mxp[pw[r-l+1]][l],mxp[pw[r-l+1]][r-(1<<pw[r-l+1])+1])
 9 #define askmnp(l,r) min(mnp[pw[r-l+1]][l],mnp[pw[r-l+1]][r-(1<<pw[r-l+1])+1])
10 #define askmxd(l,r) max(mxd[pw[r-l+1]][l],mxd[pw[r-l+1]][r-(1<<pw[r-l+1])+1])
11 #define askmnd(l,r) min(mnd[pw[r-l+1]][l],mnd[pw[r-l+1]][r-(1<<pw[r-l+1])+1])
12 const int L=1<<20|1;
13 char buffer[L],*S,*T;
14 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
15 inline int read(register int x=0,register char ch=getchar())
16 {
17     while(ch<'0'||ch>'9') ch=getchar();
18     while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
19     return x;
20 }
21 int stack[30],top;
22 inline void out(register int x){
23     do stack[++top]=x%10,x/=10;
24     while(x);
25     while(top) putchar(stack[top--]+48);
26 }
27 signed main(){
28     n=read(); pw[0]=-1; q=pow(n,0.6666);
29     for(register int i=1;i<=n;++i){
30         a[i]=read(); bl[i]=(i-1)/q+1;
31         pos[a[i]]=i; pw[i]=pw[i>>1]+1;
32         mnd[0][i]=a[i]; mxd[0][i]=a[i];
33         mnp[0][a[i]]=i; mxp[0][a[i]]=i;
34     } 
35     for(register short k=1;k<=pw[n];++k)
36         for(register int i=1;i<=n-(1<<k)+1;++i){
37             mnd[k][i]=min(mnd[k-1][i],mnd[k-1][i+(1<<k-1)]); mxd[k][i]=max(mxd[k-1][i],mxd[k-1][i+(1<<k-1)]);
38             mnp[k][i]=min(mnp[k-1][i],mnp[k-1][i+(1<<k-1)]); mxp[k][i]=max(mxp[k-1][i],mxp[k-1][i+(1<<k-1)]);
39         }
40     for(register short i=1;i<=bl[n];++i){
41         for(register short j=bl[n];j>=i;--j){
42             register int l=(i-1)*q+1,r=min(j*q,n);
43             register int vl=askmnd(l,r),vr=askmxd(l,r);
44             while(vr-vl!=r-l){
45                 l=askmnp(vl,vr); r=askmxp(vl,vr);
46                 if(bl[r]-1>j&&bl[l]+1<i){
47                     const register int tmp=l;
48                     l=min(lf[bl[tmp]+1][bl[r]-1],l);
49                     r=max(rf[bl[tmp]+1][bl[r]-1],r);
50                 }
51                 vl=askmnd(l,r); vr=askmxd(l,r);
52             }
53             lf[i][j]=l; rf[i][j]=r;
54         }
55     }
56     m=read();
57     for(register int i=1,l,r,vl,vr;i<=m;++i){
58         l=read(); r=read();
59         vl=askmnd(l,r); vr=askmxd(l,r);
60         while(vr-vl!=r-l){
61             l=askmnp(vl,vr); r=askmxp(vl,vr);
62             if(bl[r]-1>=bl[l]+1){
63                 const register int tmp=l;
64                 l=min(lf[bl[tmp]+1][bl[r]-1],l);
65                 r=max(rf[bl[tmp]+1][bl[r]-1],r);
66             }
67             vl=askmnd(l,r); vr=askmxd(l,r);
68         }
69         out(l); putchar(32); out(r); putchar(10);
70     } 
71     return 0;
72 }
698ms

 

Guess you like

Origin www.cnblogs.com/skyh/p/11306682.html