luogu 1360 阵容均衡(前缀和+差分+hash)
要求一段最大的区间里每个能力的增长值是一样的。
我们首先求一遍前缀和,发现,如果区间内[l,r]每个能力的增长值是一样的话,那么前缀和[r]和[l-1]的差分也应该是一样的。
那么我们把前缀和的差分hash一下,排个序,求出hash值相同的且跨越最远的两个端点,就是答案了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-7 # define MOD 1024523 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=100005; //Code begin... int a[N], wei[N][35]; struct Node{int hash, id;}node[N]; bool comp(Node a, Node b){ if (a.hash!=b.hash) return a.hash<b.hash; return a.id<b.id; } int main () { int n, m, x; scanf("%d%d",&n,&m); FOR(i,1,n) { scanf("%d",&x); int num=0; while (x) wei[i][++num]=x%2, x/=2; FOR(j,1,m) wei[i][j]+=wei[i-1][j]; } FOR(i,0,n) { int val=0; FOR(j,2,m) val=val*3+wei[i][j]-wei[i][j-1]; node[i].hash=val; node[i].id=i; } sort(node,node+n+1,comp); int ans=0, l, r; FOR(i,0,n) { if (i==0||node[i].hash!=node[i-1].hash) l=node[i].id; if (i==n||node[i].hash!=node[i+1].hash) r=node[i].id, ans=max(ans,r-l); } printf("%d\n",ans); return 0; }