大力施工......(10/13)剩下的三个题好像不太能写啊?
A.Palindrome(hdu6230)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6230
首先用Manacher处理出所有的回文半径,然后可以得到每个点覆盖的范围,问题转换成了,有多少对点,满足,i能覆盖j而且j也能覆盖i,我们按照回文半径从大到小进行排序,然后用线段树进行维护,然后每次查询当前点能覆盖的范围有多少点即可,更新答案,最后将该点更新到线段树上。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=5e5+5;
char Ma[MAXN];
int Mp[MAXN];
void Manacher(int len)
{
int l=len;
Ma[0]='$';
Ma[l]=0;
int mx=0,id=0;
for(int i=0;i<l;i++)
{
Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;
while(Ma[i+Mp[i]]==Ma[i-Mp[i]])Mp[i]++;
if(i+Mp[i]>mx)
{
mx=i+Mp[i];
id=i;
}
}
}
struct node
{
int id,r;
node(int _id=0,int _r=0):id(_id),r(_r){}
bool operator <(const node &a)const
{
return r>a.r;
}
}sv[MAXN];
struct seg
{
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
int sum[MAXN<<2];
inline void push_up(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
sum[rt]=0;
if(l==r)
return ;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void update(int pos,int val,int l,int r,int rt)
{
if(l==r)
{
sum[rt]=val;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)
update(pos,val,lson);
if(pos>mid)
update(pos,val,rson);
push_up(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return sum[rt];
int ret=0;
int mid=(l+r)>>1;
if(L<=mid)
ret+=query(L,R,lson);
if(mid<R)
ret+=query(L,R,rson);
return ret;
}
}se;
void solve()
{
int len;
ll ans=0;
scanf("%s",Ma+1);
len=strlen(Ma+1);
Manacher(len+1);
for(int i=1;i<=len;i++)
{
sv[i]=node(i,Mp[i]-1);
}
sort(sv+1,sv+1+len);
se.build(1,len,1);
for(int i=1;i<=len;i++)
{
int id=sv[i].id,r=sv[i].r;
ans+=se.query(max(1,id-r),min(len,id+r),1,len,1);
se.update(id,1,1,len,1);
}
printf("%lld\n",ans);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
B.K-th Number(hdu6231)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6231
二分答案,统计有多少个区间的第k大的值大于等于我们二分的答案,如果区间数大于m,就提高下界继续二分,否则降低上界。计数的时候可以采用双指针。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e5+5;
int a[MAXN],HASH[MAXN],tot,n,k;
ll m;
vector<int> sv;
int getid(int x)
{
int ret=lower_bound(HASH+1,HASH+1+tot,x)-HASH;
return ret;
}
bool judge(int mid)
{
ll ret=0;
sv.clear();
sv.push_back(0);
for(int i=1;i<=n;i++)
{
if(a[i]>=mid)
{
sv.push_back(i);
}
}
for(int i=0;i<sv.size();i++)
{
if(i<k)
continue;
ret+=(sv[i-k+1]-sv[i-k])*(n-sv[i]+1);
}
return ret>=m;
}
void solve()
{
tot=0;
scanf("%d%d%lld",&n,&k,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
HASH[++tot]=a[i];
}
sort(HASH+1,HASH+1+tot);
tot=unique(HASH+1,HASH+1+tot)-HASH-1;
for(int i=1;i<=n;i++)
{
a[i]=getid(a[i]);
}
int l=1,r=tot;
int ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(judge(mid))
{
l=mid+1;
ans=mid;
}
else
{
r=mid-1;
}
}
printf("%d\n",HASH[ans]);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
s