赞
踩
今天是可怕的一天。因为今天是lzy4896s大佬出题(博客传送门)。没错他是一个恶魔!!!(CF红名大佬)。所以又是打暴力的一天orz
以下为原创题。若有路人经过,可以看看博取一笑
【题目描述】
但重新进入队列时,如何取舍成了问题。判断下一个字符是否和当前字符相同。如果相同,则可以把自己之前的字符串处理掉进入队列,但是如果下一个字符是上一步就被处理掉的,那么当下一个字符所在的处理串的末尾的字符链接到的应该是上一串的头。这样子就出现了重复处理的混乱。无法解决。
正确解法是:将连续的字符压缩成单元,每次暴力维护单元的两端。如果单元长度为0,则合并左右两端。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define MAXN 1000010
void fff(){
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
}
char s[MAXN];
vector <pair<int,char> > lis;//记录所在字符和字符数量
vector <pair<int,char> > merge(vector<pair<int,char> > lis){//合并两端的单元
vector<pair<int,char> > res;
for (int i=0;i<lis.size();){
int j=i,sz=0;
while (j< lis.size()&&lis[j].second==lis[i].second)
sz+= lis[j].first,++j;
res.push_back(make_pair(sz,lis[i].second));
i=j;
}
return res;
}
int main(){
fff();
int len;
scanf("%d",&len);
scanf("%s",s);
for (int i=0;i<len;){
int j=i;
while (j<len&&s[j]==s[i]) j++;
lis.push_back(make_pair(j-i,s[i]));
i=j;
}
int ans=0;
while(true){
bool flag=false;
vector<pair<int,char> > tmp;
for (int i=0;i<lis.size();i++){
int t=0;
if(i&&lis[i-1].second!=lis[i].second) ++t;
if(i+1<lis.size()&&lis[i+1].second!=lis[i].second) ++t;
if(t) flag=true;
if(lis[i].first-t>0) tmp.push_back(make_pair(lis[i].first-t,lis[i].second));
}
lis=merge(tmp);
if(!flag) break;
ans++;
}
cout<<ans;
}
【题目描述】
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#define LL long long
using namespace std;
void fff(){
freopen("maxmin.in","r",stdin);
freopen("maxmin.out","w",stdout);
}
const int MAXN=500100;
int n,q,h;
int a[MAXN],bin[MAXN];
int mx[MAXN][20],mi[MAXN][20],lg[MAXN],ans1[MAXN],ans2[MAXN];
void st(){
for (int i=1;i<=n;i++){
mx[i][0]=a[i];
mi[i][0]=a[i];
}
for (int j=1;j<20;j++){
for (int i=1;i+(1<<j)-1<=n;i++){
mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
}
}
}
int query(int x,int y){
if(x>y) swap(x,y);
int k=(double)log(y-x+1)/log(2.0);
return (max(mx[x][k],mx[y-(1<<k)+1][k])-min(mi[x][k],mi[y-(1<<k)+1][k]));
}
LL Solve(int low,int high){
LL res=0;
for (int i=1,r=1;i<=n;i++){
while (r+1<=n&&query(i,r+1)<low) r++;
ans1[i]=r;
}
for (int i=1,r=1;i<=n;i++){
while (r+1<=n&&query(i,r+1)<=high) r++;
ans2[i]=r;
}
for (int i=1;i<=n;i++) if(ans1[i]<=ans2[i]) res+=ans2[i]-ans1[i];
return res;
}
int main(){
fff();
for (int i=1,h=2;h<MAXN;h<<=1,i++) lg[i];
for (int i=1;i<MAXN;i++) if(!lg[i]) lg[i]=lg[i-1];
bin[0]=1;for (int i=1;i<20;i++) bin[i]=bin[i-1]<<1;
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
st();
for (int i=1;i<=q;i++){
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",Solve(l,r));
}
return 0;
}
【题目描述】
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#define LL long long
using namespace std;
void fff(){
freopen("mean.in","r",stdin);
freopen("mean.out","w",stdout);
}
const int MAXN=200100;
int n,cnt,k;
map<LL,int> mp;
inline int Lowbit(int x){
return x&(-x);
}
int a[MAXN],c[MAXN];
LL t[MAXN],b[MAXN],ans=0,sum[MAXN];
void Insert(int x){
while (x<=cnt){
c[x]++;
x+=Lowbit(x);
}
}
int Sum(int x){
int res=0;
while (x){
res+=c[x];
x-=Lowbit(x);//这个都是树状数组的常规操作了,单点更新,区间求和
}
return res;
}
int main(){
fff();
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for (int i=0;i<=n;i++) t[i]=sum[i]-1LL*k*i,b[i]=t[i];//每个数都进行一次前缀和减去的操作
sort(b,b+n+1);//离散化的操作
for (int i=0;i<=n;i++) if(!mp[b[i]]) mp[b[i]]=++cnt;//离散化之后的排序标记
for (int i=0;i<=n;i++) t[i]=mp[t[i]];//建立映射
for (int i=0;i<=n;i++){
ans+=Sum(t[i]);//求和。
Insert(t[i]);//插入
}
cout<<ans;
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。