【HDOJ6701】Make Rounddog Happy(启发式合并)

题意:给定一个长为n的序列和k,定义子串【L,R】(L<=R)合法当:

1.max(a[L]..a[R])-(R-L+1)<=k

2.【L,R】中没有重复的数字

问合法子串的个数

n,k,a[i]<=3e5

思路:对于两个限制分开考虑

对于限制2,预处理出每个位置只考虑限制2左右最多能扩展到哪里

对于限制1,将序列以最大值的位置分治,每次只考虑包含最大值的子串

对于左右两部分其中长度比较小的一部分枚举端点

因为确定了max,另一端合法的范围也可以求出

求最大值位置用RMQ预处理

扫描二维码关注公众号,回复: 7544791 查看本文章
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 //typedef pair<ll,ll>P;
 11 #define N  300010
 12 #define M  2000010
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pb push_back
 17 #define pi acos(-1)
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 21 #define lowbit(x) x&(-x)
 22 #define Rand (rand()*(1<<16)+rand())
 23 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 24 #define ls p<<1
 25 #define rs p<<1|1
 26 
 27 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 28       double eps=1e-6;
 29       int INF=1e9;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32 
 33       int f[N<<1][25],a[N],b[N],l0[N],r0[N],n,k;
 34       ll ans;
 35 
 36 int read()
 37 {
 38    int v=0,f=1;
 39    char c=getchar();
 40    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 42    return v*f;
 43 }
 44 
 45 int query(int l,int r)
 46 {
 47     int len=r-l+1;
 48     int t=log2(len);
 49     int x=f[l][t],y=f[r-(1<<t)+1][t];
 50     if(a[x]>a[y]) return x;
 51     return y;
 52 }
 53 
 54 void solve(int l,int r)
 55 {
 56     if(l>r) return;
 57     int mid=query(l,r);
 58     int len=a[mid]-k;
 59     int L,R;
 60     if(mid-l<r-mid)
 61     {
 62         per(i,mid,l)
 63         {
 64             L=max(mid,len+i-1);
 65             R=min(r0[i],r);
 66             if(L<=R) ans+=R-L+1;
 67         }
 68     }
 69      else
 70      {
 71          rep(i,mid,r)
 72          {
 73              L=max(l,l0[i]);
 74              R=min(mid,i-len+1);
 75              if(L<=R) ans+=R-L+1;
 76          }
 77      }
 78     solve(l,mid-1);
 79     solve(mid+1,r);
 80 }
 81 
 82 int main()
 83 {
 84     //freopen("1.in","r",stdin);
 85     //freopen("1.out","w",stdout);
 86     int cas=read();
 87     while(cas--)
 88     {
 89         n=read(),k=read();
 90         rep(i,1,n) a[i]=read();
 91         mem(b,0);
 92         l0[0]=0;
 93         rep(i,1,n)
 94         {
 95             l0[i]=max(l0[i-1],b[a[i]]+1);
 96             b[a[i]]=i;
 97         }
 98         rep(i,1,n) b[a[i]]=n+1;
 99         r0[n+1]=n+1;
100         per(i,n,1)
101         {
102             r0[i]=min(r0[i+1],b[a[i]]-1);
103             b[a[i]]=i;
104         }
105         rep(i,1,n) f[i][0]=i;
106         for(int i=1;(1<<i)<=n;i++)
107          rep(j,1,n)
108          {
109              int x=f[j][i-1],y=f[j+(1<<(i-1))][i-1];
110              if(j+(1<<(i-1))>n||a[x]>a[y]) f[j][i]=x;
111               else f[j][i]=y;
112          }
113         ans=0;
114         solve(1,n);
115         printf("%I64d\n",ans);
116     }
117 
118     return 0;
119 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/11722259.html