HDU6344 调查问卷
#include
using namespace std;
const int MAX=1025;
int a[MAX];//二进制串
int num[MAX];
int main()
{
int t,n,m,K;
char str[11];
scanf("%d",&t);
for(int tc=1;tc<=t;tc++)
{
memset(a,0,sizeof(a));
scanf("%d%d%d",&n,&m,&K);
for(int i=0;i
HDU6345 子串查询
字典序满足 “abc”>"a";"b">"a";所有长度子串中单个字母字典序最小
线段树维护区间最小值的个数
#include
#include
#include
const int MAX=1e5+5;
char str[MAX];
struct node
{
char a;
int b;
node(){a='Z';b=0;}
node(node& x){a=x.a;b=x.b;}
}c[MAX*4];
void build(int rt,int l,int r)
{
if(l==r)
{
c[rt].a=str[l-1];
c[rt].b=1;
return ;
}
int mid=(l+r)>>1;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
if(c[rt*2].a==c[rt*2+1].a){c[rt]=c[rt*2];c[rt].b+=c[rt*2+1].b;}
else if(c[rt*2].a=r) return c[rt];
int mid=(l+r)>>1;
node x,y;
if (L<=mid) x=query(rt*2,l,mid,L,R);
if (R>mid) y=query(rt*2+1,mid+1,r,L,R);
if(x.a==y.a) x.b+=y.b;
else if(x.a>y.a) x=y;
return x;
}
int main()
{
int t,n,q,l,r;
scanf("%d",&t);
for(int tc=1;tc<=t;tc++)
{
printf("Case #%d:\n",tc);
scanf("%d%d",&n,&q);
scanf("%s",str);
build(1,1,n);
while(q--)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(1,1,n,l,r).b);
}
}
return 0;
}
HDU6348 序列计数
dp[ i ][ j ]表示序列长度为i取到第j个数时的种类数
用树状数组维护取到第j个数时的a[ j ]前缀和( a[ j ]的前缀和中必定不包含a[ k ],a[ k ]>a[ j ] ),同时满足 j > k且a[ j ] > a[ k ]的单调性
把求和过程的复杂度优化到O(logn)
滚动数组优化内存
#include
using namespace std;
const int MAX=1e4+5;
const long long MOD=1e9+7;
int a[MAX],n;
long long dp[2][MAX];
long long c[MAX],ans[MAX];
void add(int x,int v)
{
while(x<=n){c[x]=(c[x]+v)%MOD;x+=x&-x;}
}
long long get(int x)
{
long long sum=0;
while(x){sum=(sum+c[x])%MOD;x-=x&-x;}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
for(int tc=1;tc<=t;tc++)
{
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i=1;i<=n;i++) {scanf("%d",&a[i]);}
for(int i=1;i<=n;i++) dp[1][i]=1;ans[1]=n;
for(int i=2;i<=n;i++)
{
ans[i]=0;
if(ans[i-1]==0) continue;
memset(c,0,sizeof(c));
for(int j=1;j<=n;j++)
{
dp[i%2][j]=get(a[j]-1);
add(a[j],dp[(i-1)%2][j]);
ans[i]=(ans[i]+dp[i%2][j])%MOD;
}
}
printf("Case #%d:",tc);
for(int i=1;i<=n;i++) printf(" %I64d",ans[i]);
putchar('\n');
}
return 0;
}
HDU6349 三原色图
Kruskal计算最小生成树权值,优先队列维护最小边权
#include
using namespace std;
const int MAX=1e2+5;
const int INF=0x3f3f3f3f;
int f[MAX],tot1,tot2;
struct Edge
{
int a,b,w;
Edge(){}
Edge(int a_,int b_,int v_)
{
a=a_;b=b_;w=v_;
}
Edge(const Edge &e)
{
a=e.a;b=e.b;w=e.w;
}
}e1[MAX],e2[MAX];
int q1[MAX],q2[MAX],L1,R1,L2,R2;
void add1(Edge &e)
{
e1[tot1++]=e;
}
void add2(Edge &e)
{
e2[tot2++]=e;
}
int find(int x)
{
if(f[x]==-1) return x;
else return f[x]=find(f[x]);
}
bool cmp(Edge &ea,Edge &eb)
{
return ea.w=INF) printf("-1\n");
else printf("%d\n",ans);
int as1=INF,as2=INF;
if(L1<=R1) as1=q1[L1++];
if(L2<=R2) as2=q2[L2++];
a1=a1+as1;
a2=a2+as2;
}
}
return 0;
}