P5167 xtq的神笔
生活随笔
收集整理的這篇文章主要介紹了
P5167 xtq的神笔
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
題解
倍增也好二分也好,果然復雜度只要和\(\log\)插上關系就沒我啥事了……
首先由一個顯而易見然而我完全沒有發現的結論,設\(calc(l,r)\)表示區間\([l,r]\)的\(or\)起來加區間的\(and\)起來加區間的\(\gcd\)起來(就是題目里說的那個亂七八糟的東西)的值,那么我們固定右端點\(r\),左端點逐漸座椅的過程中,\(calc(l,r)\)的變化的次數為\(O(\log v)\),其中\(v\)是所有格子的值域
證明:左移的時候,\(or\)和\(and\)每次變化都會改變一個二進制位,最多改變\(O(\log v)\)次,而\(gcd\)因為每次都會變成自己的因子,值必然不超過之前的一半,所以總的變化次數也是\(O(\log v)\)
于是我們可以把之前的所有位置給分成\(O(\log v)\)段,其中每一段里面所有位置到當前位置的\(or,and,gcd\)都相等,這樣可以用一個雙向鏈表來維護,每次加入一個新位置的時候之前的區間不可能被拆分,只可能被合并。于是每一次加入之后合并,然后在這些所有的區間里找最優的就是了
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i) #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){R int res,f=1;R char ch;while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');return res*f; } char sr[1<<21],z[20];int C=-1,Z=0; inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} void print(R int x){if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;while(z[++Z]=x%10+48,x/=10);while(sr[++C]=z[Z],--Z);sr[++C]='\n'; } const int N=3e5+5,L=19; int Log[N],a[N],st1[N][L],st2[N][L],st3[N][L]; struct node{ll v1,v2,v3,f;}p[N],res;int las[N],nxt[N],h,t,tot;ll f[N]; int n,k; int gcd(int x,int y){return y?gcd(y,x%y):x;} void ins(const node &b){p[++tot]=b,nxt[t]=tot,las[tot]=t;t=tot,nxt[tot]=-1; } void del(R int pos){nxt[las[pos]]=nxt[pos];pos==t?t=las[pos]:las[nxt[pos]]=las[pos]; } int query_or(R int l,R int r){int k=Log[r-l+1];return st1[l][k]|st1[r-(1<<k)+1][k]; } int query_and(R int l,R int r){int k=Log[r-l+1];return st2[l][k]&st2[r-(1<<k)+1][k]; } int query_gcd(R int l,R int r){int k=Log[r-l+1];return gcd(st3[l][k],st3[r-(1<<k)+1][k]); } void clr(){tot=h=t=0;memset(nxt,0,sizeof(nxt)),memset(las,0,sizeof(las));memset(f,0xef,sizeof(f)),nxt[0]=-1; } int main(){ // freopen("testdata.in","r",stdin);int T=read();fp(i,2,N-5)Log[i]=Log[i>>1]+1;while(T--){clr();n=read(),k=read();fp(i,1,n)st1[i][0]=st2[i][0]=st3[i][0]=a[i]=read();fp(i,1,k)f[i-1]=read();for(R int j=1;(1<<j)<=n;++j)fp(i,1,n-(1<<j)+1){st1[i][j]=st1[i][j-1]|st1[i+(1<<j-1)][j-1];st2[i][j]=st2[i][j-1]&st2[i+(1<<j-1)][j-1];st3[i][j]=gcd(st3[i][j-1],st3[i+(1<<j-1)][j-1]);}fp(i,k,n){int pos=nxt[h];while(pos>=0){p[pos].v1|=a[i],p[pos].v2&=a[i],p[pos].v3=gcd(p[pos].v3,a[i]);pos=nxt[pos];}res={query_or(i-k+1,i),query_and(i-k+1,i),query_gcd(i-k+1,i),f[i-k]};ins(res),pos=nxt[h];while(pos>=0&&nxt[pos]>=0){if(p[pos].v1==p[nxt[pos]].v1&&p[pos].v2==p[nxt[pos]].v2&&p[pos].v3==p[nxt[pos]].v3)cmax(p[pos].f,p[nxt[pos]].f),del(nxt[pos]);pos=nxt[pos];}pos=nxt[h];while(pos>=0)cmax(f[i],p[pos].v1+p[pos].v2+p[pos].v3+p[pos].f),pos=nxt[pos];}printf("%lld\n",f[n]);}return 0; }轉載于:https://www.cnblogs.com/bztMinamoto/p/10206107.html
總結
以上是生活随笔為你收集整理的P5167 xtq的神笔的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不用梯子——每日领取5块钱的ChatGP
- 下一篇: app中加载h5页面白屏问题