czy的后宫3(莫队)

【题目描述】

上次czy在机房妥善安排了他的后宫之后,他发现可以将他的妹子分为c种,他经常会考虑这样一个问题:在[l,r]的妹子中间,能挑选出多少不同类型的妹子呢?

注意:由于czy非常丧尸,所以他要求在所挑选的妹子类型在[l,r]中出现次数为正偶数,你懂得。

问题简述:n个数,m次询问,每次问[l,r]区间有多少个数恰好出现正偶数次

【输入格式】

第一行3个整数,表示n,c,m

第二行n个数,每个数Ai在[1,c]之间,表示一个Ai类型的妹子

接下来m行,每行两个整数l,r,表示询问[l,r]这个区间的答案

【输出格式】

有m行,表示第i次询问的答案

【样例输入】

5 5 3

1 1 2 2 3

1 5

3 4

2 3

【样例输出】

2

1

0

【数据范围】

共有10组测试数据

1-4组n,m=500,2000,5000,10000,c=1000

5-7组n,m=20000,30000,40000,c=10000

8-10组n,m=50000,80000,100000,c=100000

数据保证随机生成

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
int n,m,c,vis[maxn],a[maxn],l,r,ans;
int main(){
//freopen("Cola.txt","r",stdin);
freopen("harem.in","r",stdin);
freopen("harem.out","w",stdout);
scanf("%d%d%d",&n,&c,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=m;i++){
scanf("%d%d",&l,&r);ans=;
memset(vis,,sizeof(vis));
for(int j=l;j<=r;j++)vis[a[j]]++;
for(int j=;j<=c;j++)
if(vis[j]%==&&vis[j])ans++;
printf("%d\n",ans);
}
}

40分 暴力(我以为只能得20分)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=;
struct node{
int l,r,ans,id;
}q[maxn];
int cnt[maxn],a[maxn],belong[maxn],n,m,c;
int cmp1(node x,node y){
if(belong[x.l]!=belong[y.l])
return belong[x.l]<belong[y.l];
return x.r<y.r;
}
int cmp2(node x,node y){
return x.id<y.id;
}
int main(){
//freopen("Cola.txt","r",stdin);
freopen("harem.in","r",stdin);
freopen("harem.out","w",stdout);
scanf("%d%d%d",&n,&c,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
int block=(int)(sqrt(n));
for(int i=;i<=n;i++)belong[i]=(i-)/block+;
for(int i=;i<=m;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+,q+m+,cmp1);
int ans=,l=,r=;
for(int i=;i<=m;i++){
while(l>q[i].l){
l--;cnt[a[l]]++;
if(cnt[a[l]]%==)ans++;
if(cnt[a[l]]%==&&cnt[a[l]]!=)ans--;
}
while(r<q[i].r){
r++;cnt[a[r]]++;
if(cnt[a[r]]%==)ans++;
if(cnt[a[r]]%==&&cnt[a[r]]!=)ans--;
}
while(l<q[i].l){
cnt[a[l]]--;
if(cnt[a[l]]%==&&cnt[a[l]]!=)ans++;
if(cnt[a[l]]%==)ans--;
l++;
}
while(r>q[i].r){
cnt[a[r]]--;
if(cnt[a[r]]%==&&cnt[a[r]]!=)ans++;
if(cnt[a[r]]%==)ans--;
r--;
}
q[i].ans=ans;
}
sort(q+,q+m+,cmp2);
for(int i=;i<=m;i++){
printf("%d\n",q[i].ans);
}
}

100分 莫队

czy的后宫4  (dp)

【问题描述】

czy有很多妹子,妹子虽然数量很多,但是质量不容乐观,她们的美丽值全部为负数(喜闻乐见)。

czy每天都要带N个妹子到机房,她们都有一个独一无二的美丽值,美丽值为-1到-N之间的整数。他想要把这些妹子排成一个波动序列,这样相对“漂亮”(美丽值的绝对值较小)的妹子可以与她旁边的两个美丽值的绝对值较大的妹子形成鲜明的对比,整个序列相对将更加“美观”(不再那么无法直视)。

一个序列是波动序列仅当序列中的每个数比周围的两个数都大或都小(如果有的话)。

现在czy希望知道,长度为N的波动序列有多少种。两种序列A和B不同当且仅当存在一个i,使得Ai≠Bi。由于这个数目可能很大,你只对它除以P的余数感兴趣。

【输入格式】

输入文件czy.in仅含一行,两个正整数N, P。

【输出格式】

输出文件czy.out仅含一行,一个非负整数,表示你所求的答案对P取余之后的结果。

【样例输入输出】

czy.in

4 7

czy.out

3

说明:共有10种可能的序列,它们是:  1324 1423 2143 2314 2413  3142 3241 3412 4132 4231

(忽略负号)

【数据规模和约定】

对于20%的数据,满足N≤10;

对于40%的数据,满足N≤18;

对于70%的数据,满足N≤550;

对于100%的数据,满足3≤N≤4200,P≤10^9。

/*20分 暴力*/
#include<iostream>
#include<cstdio>
using namespace std;
int n,p,ans;
bool vis[];
void dfs(int pre,int now,bool rel){
if(now==n+){
ans++;
if(ans>=p)ans-=p;
return;
}
for(int i=;i<=n;i++){
if(!vis[i]){
if(rel==){
if(i<pre){
vis[i]=;
dfs(i,now+,!rel);
vis[i]=;
}
}
if(rel==){
if(i>pre){
vis[i]=;
dfs(i,now+,!rel);
vis[i]=;
}
}
}
}
}
int main(){
freopen("czy.in","r",stdin);
freopen("czy.out","w",stdout);
scanf("%d%d",&n,&p);
dfs(,,);
dfs(,,);
printf("%d",ans);
}

20分 暴力

/*
f[i][j]第一位为[1,j]且第一位下降的1~i的合法排列数,先给出结论:f[i][j] = f[i][j – 1] + f[i – 1][i – j]
首先是要加上[1,j – 1]的合法排列数,然后考虑j开头的第一位下降合法排列数
这个就是求以[1,j]开头的1~n-1的第一位上升合法排列数(这个应该可以YY一下吧..)
但是第一位上升的合法排列数我们是没有算的,但注意到第一位上升和第一位下降具有对称性
所以求以[1,j]开头的1~n-1的第一位上升合法排列数就是f[i – 1][i – j]
然后如果开[4200][4200]的int的话正好会被卡掉,所以必须滚动数组..
*/
#include<iostream>
#include<cstdio>
using namespace std;
int n,p;
int dp[][];
int main(){
scanf("%d%d",&n,&p);
int x;
dp[][]=;
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
x=i&;
dp[x][j]=dp[x][j-]+dp[x^][i-j];
dp[x][j]%=p;
}
}
printf("%d",(long long)(dp[n&][n]*)%p);
return ;
}

100分 dp

czy的后宫5(树形dp)

描述

czy要召集他的妹子,但是由于条件有限,可能每个妹子不能都去,但每个妹子都有一个美丽值,czy希望来的妹子们的美丽值总和最大(虽然……)。

czy有一个周密的电话通知网络,它其实就是一棵树,根结点为czy,他可以通知一些妹子(毕竟他不认识他的所有妹子嘛),称为他的下线(也就是儿子节点),下线们继续通知自己的下线。任何妹子都可以不去,但是任何一个妹子如果要去,则她的上线(也就是她的父亲节点)一定要去。

为了使妹子美丽值总和最大,czy想安排一下,(非强制)让一些妹子去。但是妹子数很多,人脑是难以应付的,所以他想让你用电脑解决。

输入格式

输入第一行两个整数n,m表示有n个妹子,至多只能去m个妹子。(1<=m<=n)

接下来2*n行,每两行代表一个妹子的信息(如果这个妹子没有子节点,就只有一行)。

每个妹子的第一行两个整数p,s,表示这个妹子美丽值为p,子节点个数s;(-100<=p<=100)

第二行s个整数,表示这个妹子的子节点的编号。czy的编号一定为1。

对于20%数据1<=n<=10

对于60%数据1<=n<=100

对于100%数据1<=n<=1000

输出格式

输出一个整数,表示权值的最大值。

样例输入

8 5

100 2

2 3

79 2

4 5

109 3

6 7 8

100 0

100 0

100 0

101 0

108 0

样例输出

518

/*
由于给出数据可能构成多叉树,先左儿子右兄弟转换成二叉树
dp[i][j]表示讨论到i号节点,最多选j个的最大值
树形dp,从叶子节点开始(深搜到底再执行dp方程)
此时的节点分为取和不取两种情况
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
int n,m,dp[maxn][maxn],a[maxn];
struct node{
int l,r;
}tr[maxn];
void Insert(int from,int to){
int p=tr[from].l;
if(tr[from].l==)tr[from].l=to;
else{
while(tr[p].r!=)p=tr[p].r;
tr[p].r=to;
}
}
void DP(int now,int sum){
if(now==||sum==){dp[now][sum]=;return;}
if(dp[now][sum]!=-)return;
DP(tr[now].r,sum);//不选now节点
dp[now][sum]=dp[tr[now].r][sum];
for(int i=;i<sum;i++){//选now节点
DP(tr[now].r,i);
DP(tr[now].l,sum--i);
dp[now][sum]=max(dp[now][sum],dp[tr[now].r][i]+dp[tr[now].l][sum--i]+a[now]);
}
}
int main(){
freopen("task.in","r",stdin);
freopen("task.out","w",stdout);
scanf("%d%d",&n,&m);
int x,y;
memset(dp,-,sizeof(dp));
for(int i=;i<=n;i++){
scanf("%d%d",&a[i],&x);
for(int j=;j<=x;j++){
scanf("%d",&y);
Insert(i,y);
}
}
DP(,m);
printf("%d",dp[][m]);
}

80分 树形dp

/*
同样是dp
先跑一边dfs,记录下各点的dfs序和各子树的大小,为了方便切换子树
dp[i][j]表示讨论到i号节点,正好选j个的最优解。
dp[i+1][j-1]+v[list[i]]是选i号节点
dp[i+sz[list[i]]][j]是不选i号节点,i+sz[list[i]]是与i为兄弟关系的另一棵子树的根节点编号
由于一共选了几个是不确定的,所以最终答案在dp[1][1...m]里面找
可以一个都不选,所以最小为0,不会出现负数的情况
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
int n,m,dp[maxn][maxn],sz[maxn],list[maxn],a[maxn][maxn],s[maxn],v[maxn];
int cnt;
void dfs(int x){
list[++cnt]=x;
sz[x]=;
for(int i=;i<=sz[x];i++){
if(a[x][i])dfs(a[x][i]);
sz[x]+=sz[a[x][i]];
}
}
int main(){
//freopen("Cola.txt","r",stdin);
freopen("task.in","r",stdin);
freopen("task.out","w",stdout);
memset(dp,,sizeof(dp));
scanf("%d%d",&n,&m);
int x;
for(int i=;i<=n;++i){
scanf("%d%d",&v[i],&s[i]);
for(int j=;j<=s[i];++j){
scanf("%d",&x);
a[i][j]=x;
}
}
dfs();
for(int i=;i<=n;i++){
dp[i][]=;
dp[i][]=v[list[i]];
}
for(int i=n-;i>=;i--){
for(int j=;j<=m;j++){
dp[i][j]=max(dp[i+][j-]+v[list[i]],dp[i+sz[list[i]]][j]);
}
}
int ans=;
for(int i=;i<=m;i++)ans=max(ans,dp[][i]);
printf("%d",ans);
}

100分 dfs序优化dp

czy的后宫6

题目描述

众所周知的是丧尸czy有很多妹子(虽然很多但是质量不容乐观QAQ),今天czy把n个妹子排成一行来检阅。但是czy的妹子的质量实在……所以czy看不下去了。检阅了第i个妹子会增加czy a[i]的肾虚值,他打算在检阅过程中最多休息m次(一开始检阅算0次休息,就是说czy最多可以检阅m+1次),每次休息过后czy又会龙精虎猛的继续检阅。问怎样分配才能使得czy在检阅过程中的最大肾虚值最小。

当然这么简单的问题czy早就会做啦……他原来还想算算满足肾虚值最小的条件下有几种方案,但是他太虚了,所以这个问题也交给你啦。你只要输出方案数mod 32123的值即可。

输入格式

第一行输入两个正整数n、m,表示czy的妹子数、最多的休息次数

接下来2到n+1行每行输入一个数a[i],意义见上

输出格式

第一行输出一个数s,表示最小的肾虚值

第二行输出一个数t,表示方案数

样例输入

4 2

3

4

5

2

样例输出

7

3

样例解释

最小的肾虚值为7

分法有3种:34|5|2,34|52,3|4|52

‘|’表示休息

数据范围

有30%的数据,1<=n<=20

另30%的数据,1<=n<=200

另30%的数据,1<=n<=5000,1<=m<=min(n-1,1000),1<=a[i]<=1000

另10%的数据,1<=n<=20000,1<=m<=1000,a[i]只有1、2

保证80%数据随机生成,在计算过程中不会爆int

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=;
int n,m,a[maxn],ans,Ans;
bool check(int x){
int sum=,cnt=;
for(int i=;i<=n;i++){
if(sum+a[i]>x){
cnt++;
sum=a[i];
}
else sum+=a[i];
if(cnt>m)return ;
}
return ;
}
bool OK(int now,int sum){
for(int i=now;i<=n;i++)sum+=a[i];
if(sum>ans)return ;
return ;
}
void dfs(int now,int sum,int cnt){
if(cnt>m)return;
if(now==n){
if(sum+a[n]>ans&&cnt<m)Ans++;
if(sum+a[n]<=ans){
Ans++;
if(cnt<m)Ans++;
}
if(Ans>=)Ans-=;
return;
}
if(sum+a[now]>ans){
dfs(now+,a[now],cnt+);
return;
}
if(cnt==m){
if(!OK(now,sum))return;
else {
Ans++;
if(Ans>=)Ans-=;
return;
}
}
if(sum+a[now]<=ans){
dfs(now+,sum+a[now],cnt);
dfs(now+,a[now],cnt+);
}
}
int main(){
//freopen("Cola.txt","r",stdin);
freopen("visit.in","r",stdin);
freopen("visit.out","w",stdout);
int l=,r=;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%d",&a[i]),r+=a[i];
while(l<=r){
int mid=(l+r)>>;
if(check(mid))
ans=mid,r=mid-;
else l=mid+;
}
printf("%d\n",ans);
dfs(,a[],);
if(Ans>=)Ans-=;
printf("%d",Ans);
}

30分 二分答案+暴力

蒟蒻czy又被D飞了

【题目描述】

机房里的各路巨神天天D蒟蒻CZY,早已是他们的日常任务了。(今天的机房也是很和平呢)

这一次他们安排好了一种方式来D蒟蒻Czy。每个人每次都能把Czy D飞一个高度(让Czy的高度+a[i]),由于他们的精♂力有限(尤其是某些后宫王),要保留体力应对接下来的战♂斗,所以他们每个人只会D Czy k[i]次。由于他们每个人的D人能力不同,各有所长,所以他们每个人都在Czy到一定高度h[i]以后良心发现,任由Czy自生自灭,回去玩达尔文进化岛了。(神犇们:计划通

所以Czy想知道他的速度是否能达到第二宇宙速度,离开这个可怕的地方。但是Czy太弱了,所以这个问题就交给了未来集训队的你。但是你这么吊,哪里屑解答Czy蒟蒻的问题。于是你打算只告诉他最高会飞到什么高度,让他自己算自己的速度去。(蒟蒻无人权)

【输入格式】 fly.in

第1行:1个整数N(1<=N<=100)N表示机房里有多少人今天要D 蒟蒻Czy

接下里N行,每行描述一个神犇的信息  a[i] h[i] k[i]

【输出格式】 fly.out

第1行:1个整数H,表示Czy最高会被神犇们D到哪里去

【样例输入】

7

8 35 1

5 35 1

15 35 1

8 35 1

10 35 1

4 35 1

2 35 1

【样例输出】

35

数据范围

对于40%的数据  所有人的k[i]==1, n<=10,h[i]<=100 且所有人的h[i]相等(天地良心,不要不信

对于100%的数据  1<=k[i]<=30,1<=h[i]<=10000,  1<=a[i]<=200

不做这题的下场如下

2014-7-17 NOIP模拟赛的更多相关文章

  1. 10.17 NOIP模拟赛

    目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...

  2. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  3. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  4. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  5. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  6. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  7. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  8. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  9. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  10. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

随机推荐

  1. RESTful设计模式状态码code说明

    一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. 下面是标准RESTfu ...

  2. Hadoop实战-MapReduce之分组(group-by)统计(七)

    1.数据准备 使用MapReduce计算age.txt中年龄最大.最小.均值name,min,max,countMike,35,20,1Mike,5,15,2Mike,20,13,1Steven,40 ...

  3. Python 的枚举类型

    起步 Python 中的枚举类型 Python 的原生类型中并不包含枚举类型.为了提供更好的解决方案,Python 通过 PEP 435 在 3.4 版本中添加了 enum 标准库. 枚举类型可以看作 ...

  4. uboot之logo显示【转】

    本文转载自:http://blog.csdn.net/tuwenqi2013/article/details/60583735 版权声明:本文为博主原创文章,博主欢迎各位转载. 一.logo的调用流程 ...

  5. platform_set_drvdata()/platform_get_drvdata()/container_of()【转】

    本文转载自:http://blog.csdn.net/angle_birds/article/details/8443695 platform_set_drvdata(struct platform_ ...

  6. BZOJ2120 数颜色 —— 待修改莫队

    题目链接:https://vjudge.net/problem/HYSBZ-2120 2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit:  ...

  7. 2017广东工业大学程序设计竞赛 E倒水(Water)

    题目链接:http://www.gdutcode.sinaapp.com/problem.php?cid=1057&pid=4 题解: 方法一:对n取2的对数: 取对数的公式:s = log( ...

  8. postNotificationName 消息传递详解

      1.定义消息创建的关联值 也就是找到方法的标志 NSString *const GameToIPhoneNotification = @"GameToIPhoneNotification ...

  9. 使用libcurl进行HTTP GET操作

    Working example how to do a GET request with libcurl and save it to a string variable for future use ...

  10. fatal error C1902: 程序数据库管理器不匹配;请检查安装解决

    http://blog.sina.com.cn/s/blog_9f4bc8e301015uhz.html 1.错误提示:VS2008编译错误fatal error C1902: 程序数据库管理器不匹配 ...