杭电多校2
1004 I love counting
思路:用莫队处理每次询问,并将a[i]对应的纵坐标进行分块,用num数组记录每个a[i]的出现的个数,用sum表示每个块里面不为0的数的个数。对于每个j,求出小于他的所有值,最后加上异或后等于b的情况;
代码:
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1e6+10;
int n,q;
int siz,len;
int a[maxn];
int belong[maxn];
int now;
int ans[maxn];
int num[maxn],sum[maxn];
int k;
struct node
{
int l,r,a,b,id;
}e[maxn];
bool cmp(node a,node b)
{
return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.l]&1)?a.r<b.r:a.r>b.r);//处理查询的排序方法
}
void add(int x)
{
if(++num[x]==1)sum[x/k]++;
}
void del(int x)
{
if(--num[x]==0)sum[x/k]--;
}
int calc(int x)
{
int ans=0;
for(int i=0;i<x/k;i++)
ans+=sum[i];
for(int i=(x/k)*k;i<=x;i++)
ans+=(num[i]!=0);
return ans;
}
int main()
{
scanf("%d",&n);
k=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
siz=sqrt(n);
len=ceil((double)n/siz);
for(int i=1;i<=siz;i++)
{
for(int j=1;j<=len;j++)
{
belong[j+(i-1)*len]=i;
}
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d%d%d%d",&e[i].l,&e[i].r,&e[i].a,&e[i].b);
e[i].id=i;
}
sort(e+1,e+1+q,cmp);
int l=1,r=0;
for(int i=1;i<=q;i++)
{
int s=0;
int p=0;
int ql=e[i].l;
int qr=e[i].r;
while(l<ql)del(a[l++]);
while(l>ql)add(a[--l]);
while(r>qr)del(a[r--]);
while(r<qr)add(a[++r]);
int a=e[i].a;
int b=e[i].b;
for(int j=19;j>=0;j--)
{
p=s;
if((b>>j)&1)
{
if((a>>j)&1)
{
p|=(1<<j);
}else
{
s|=(1<<j);
}
ans[e[i].id]+=calc(p+(1<<j)-1)-calc(p-1);
}else
{
if((a>>j)&1)
{
s|=(1<<j);
}
}
}
ans[e[i].id]+=(num[e[i].a^e[i].b]!=0);
}
for(int i=1;i<=q;i++)
{
printf("%d\n",ans[i]);
}
}
1008 I love exam
思路:先将每个学科分开,看作单个背包,算出每个背包各个容量下的最大价值,主要要保证分数不能超过100。
然后我们需要将各学科合并。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
#define pb(x) push_back(x)
#define pair4 pair<pair<int,int>,pair<int,int> >
#define fi first
#define se second
using namespace std;
const int maxn = 3e5+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
int n,m,cnt,s,p;
string a;
map<string,int>mp;
vector<vector<pair<int,int> > >vec(15000+10);
int f[100][15000+10];
int dp[100][15000+10][5];
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>a;
mp[a]=i;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int u,v;
cin>>a>>u>>v;
vec[mp[a]].push_back(make_pair(u,v));
}
scanf("%d%d",&s,&p);
ms(f,-inf);
for(int i=1;i<=n;i++)
{
f[i][0]=0;
for(int j=0;j<vec[i].size();j++)
{
for(int z=s;z>=0;z--)
{
int w=vec[i][j].se;
int v=vec[i][j].fi;
if(z>=w)
f[i][z]=max(min(100,f[i][z-w]+v),f[i][z]);
}
}
}
ms(dp,-inf);
dp[0][0][0]=0;
for(int i=1;i<=n;i++)//第i门
{
for(int j=0;j<=s;j++)//花费j时间
{
for(int t=0;t<=s;t++)//背包容量
{
for(int z=0;z<=min(i,p);z++)//挂科数目
{
int x=0;
if(f[i][j]<60)
{
x=1;
}
if(t>=j&&x==0)
dp[i][t][z]=max(dp[i][t][z],dp[i-1][t-j][z]+f[i][j]);
else if(t>=j&&z>0)
dp[i][t][z]=max(dp[i][t][z],dp[i-1][t-j][z-x]+f[i][j]);
}
}
}
}
int ma=-1;
for(int i=0;i<=s;i++)
{
for(int j=0;j<=p;j++)
{
ma=max(ma,dp[n][i][j]);
}
}
printf("%d\n",ma);
mp.clear();
for(int i=1;i<=n;i++)vec[i].clear();
}
}