• [LOJ#6468.] 魔法


    官方题解

    看了题解才会做..

    首先考虑如果所有询问的点都是[1,n]的做法,如果询问是[l,r]只需要把多余的去掉就好了

    然后要把问题转化为一个点对其他附近的点的贡献

    记$pre[i]$为第i个位置的数字上一次出现的位置,记$nxt[i]$为第i个位置上的数字下一次出现的位置,显然这些东西都能扫一遍求出来

    然后对于一个点,它能做出贡献的区间是:$$[frac{pre[i]+i}{2}+1,frac{i+nxt[i]}{2}]$$

    如果不在这个区间内的话,显然选择$pre[i]$或者$nxt[i]$更优秀

    我们把这个区间分成两份$$[frac{pre[i]+i}{2}+1,i] and [i,frac{i+nxt[i]}{2}]$$

    对于前一个区间这个点i对点j做出的贡献为$i-j$,对于后一个区间则为$j-i$

    我们维护两个树状数组,一个记录自己点上的坐标被加/减了多少次,另一个记录这个点上被别的点贡献了多少权值即可

     

    如果不是每次询问[1,n]的话,我们把询问记录下来,离线差分解决即可

     

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define inf (0x3f3f3f3f)
     4 #define writeln(x)  write(x),puts("")
     5 #define writep(x)   write(x),putchar(' ')
     6 using namespace std;
     7 inline int read(){
     8     int ans=0,f=1;char chr=getchar();
     9     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
    10     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
    11     return ans*f;
    12 }void write(int x){
    13     if(x<0) putchar('-'),x=-x;
    14     if(x>9) write(x/10);
    15     putchar(x%10+'0');
    16 }const int M = 2e5+5;
    17 int n,nxt[M],pre[M],T,cnt[M],a[M],ans[M];
    18 struct Que{int pos,opt,id;};
    19 struct P{int s[M];
    20     #define lowbit(x) (x&-x)
    21     inline void Update(int x,int y){for(;x<=n;x+=lowbit(x))s[x]+=y;}
    22     inline int  Query(int x,int ans=0){for(;x;x-=lowbit(x))ans+=s[x];return ans;}
    23     inline void Update(int l,int r,int x){Update(l,x),Update(r+1,-x);}
    24     #undef lowbit
    25 }T1,T2;vector<int>tp[M];vector<Que>Q[M];
    26 inline void Update(int i){
    27     int l=(pre[i]+i>>1)+1;if(l<1)l=1;
    28     T1.Update(l,i,i),T2.Update(l,i,-1);
    29     int r=nxt[i]+i>>1;if(r>n)r=n;
    30     T1.Update(i,r,-i),T2.Update(i,r,1);
    31 }inline int Query(int pos){
    32     return T2.Query(pos)*pos+T1.Query(pos);
    33 }signed main(){
    34     n=read(),T=read();
    35     for(int i=1;i<=n;i++){
    36         a[i]=read();pre[i]=-inf,nxt[i]=inf;
    37         if(tp[a[i]].size()) nxt[pre[i]=*tp[a[i]].rbegin()]=i;
    38         tp[a[i]].push_back(i);
    39     }for(int i=1;i<=T;i++){
    40         int pos=read(),l=read(),r=read();
    41         Q[l-1].push_back((Que){pos,-1,i});
    42         Q[r].push_back((Que){pos,1,i});
    43     }for(int i=1;i<=n;i++){
    44         for(int pos:tp[i])Update(pos);
    45         for(Que now:Q[i]) ans[now.id]+=now.opt*Query(now.pos);
    46     }for(int i=1;i<=T;i++)printf("%lld
    ",ans[i]);
    47     return 0;
    48 }

     

     

     

  • 相关阅读:
    Java++:一文搞懂分布式锁及其业务场景
    Get MSN ADS
    删除废弃的全文索引
    门户网页分页(pagination Style)
    SQL Server 无法查看属性
    FileUpload Control In ASP.NET2.0
    根据IP和掩码获取主机IP区域
    IIS 使用域用户
    Get MSN ADS by xmlHttpRequest
    二进制时钟
  • 原文地址:https://www.cnblogs.com/zhenglw/p/11769611.html
Copyright © 2020-2023  润新知