期望得分:100+100+40=240

实际得分:100+40+0=140

T1 一道图论神题(god)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK有一张无向图G={V,E},这张无向图有n个点m条边组成。并且这是一张带权图,只有点权。

LYK想把这个图删干净,它的方法是这样的。每次选择一个点,将它删掉,但删这个点是需要代价的。假设与这个点相连的还没被删掉的点是u1,u2,…,uk。LYK将会增加a[u1],a[u2],…,a[uk]的疲劳值。

它想将所有点都删掉,并且删完后自己的疲劳值之和最小。你能帮帮它吗?

输入格式(god.in)

第一行两个数n,m表示一张n个点m条边的图。

第二行n个数ai表示点权。

接下来m行每行三个数u,v,表示有一条连接u,v的边。数据保证任意两个点之间最多一条边相连,并且不存在自环。

输出格式(god.out)

你需要输出这个最小疲劳值是多少。

输入样例

4 3

10 20 30 40

1 4

1 2

2 3

输出样例

40

样例解释

一个合理的方法是先删4号点,此时有10点疲劳值。接下来删3号点,获得20点疲劳值,再删2号点,获得10点疲劳值,最后删1号点,没有疲劳值。总计40点疲劳值。

对于30%的数据n<=10。

对于60%的数据n,m<=1000。

对于100%的数据1<=n,m,ai<=100000

m条边,疲劳值就会计算m次

所以可以贪心的选择 每条边的疲劳值小的点累计

正确性:如果每条无向边改为疲劳值大的点向疲劳值小的点的有向边,那么这张图就是DAG

#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int val[N];
void out(long long x)
{
if(x/) out(x/);
putchar(x%+'');
}
int main()
{
freopen("god.in","r",stdin);
freopen("god.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&val[i]);
int u,v;
long long ans=;
for(int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
ans+=min(val[u],val[v]);
}
out(ans);
}

T2 位运算2(bit)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK拥有一个十进制的数N。它赋予了N一个新的意义:不考虑N的符号,将N每一位都拆开来后再加起来就是N所拥有的价值。例如数字123拥有6的价值,数字999拥有27的价值,数字-233拥有8的价值。

假设数字N的价值是K,LYK想找到一个价值是K+1的数字,当然这个答案实在太多了,LYK想使得这个价值为K+1的数字尽可能大,并且需要保证这个数字小于N。

输入格式(bit.in)

一个整数N。

输出格式(bit.out)

一个数表示答案。你需要输出一个整数,且这个数不包含前导0。

输入样例1

199

输出样例1

-299

输入样例2

1520

输出样例2

1512

对于20%的数据|N|<=10

对于40%的数据|N|<=100

对于60%的数据|N|<=10^9

对于80%的数据|N|<=10^1000

对于100%的数据|N|<=10^100000。

正数和负数分开讨论

正数:

① 设第i位之后的数位之和为gather,第i位为num,那么如果gather<=(len-i)*9+num-1,

最优解就是第i位为num-1,之后的数贪心填当前能填的最大的,之前就是原数

② 找不到满足条件①的,最优解只能是负数,那就是找绝对值最小的那个

设数位之和为tot,那么第一位为tot%9,后面tot/9个9

负数:

从后往前找到第一个小于9的位置,这个位置的数+1,其余位置的数不变

考场上忘了判断负数,WA了5个点

正数的情况①中,没有判断第i位可能是要输出的第一位,且num-1=0,WA了1个点

#include<cstdio>
#include<cstring>
using namespace std;
char s[];
int num[],tot,gather;
int main()
{
freopen("bit.in","r",stdin);
freopen("bit.out","w",stdout);
scanf("%s",s);
int len=strlen(s);
if(s[]!='-')
{
for(int i=;i<len;i++) num[i]=s[i]-'',tot+=num[i];
gather=num[len-]+;
for(int i=len-;i>=;i--)
{
gather+=num[i];
if(!num[i]) continue;
if((len-i-)*+num[i]->=gather)
{
bool ok=false;
for(int j=;j<i;j++) ok=true,printf("%d",num[j]);
if(ok || num[i]>) printf("%d",num[i]-);
gather-=(num[i]-);
for(int j=i+;j<len;j++)
if(gather>=) printf(""),gather-=;
else printf("%d",gather),gather=;
return ;
}
}
putchar('-');
tot++;
int n=tot/;
if(tot%) printf("%d",tot%);
for(int i=;i<=n;i++) printf("");
return ;
}
else
{
putchar('-');
for(int i=;i<len;i++) num[i]=s[i]-'';
for(int i=len-;i;i--)
if(num[i]<)
{
for(int j=;j<i;j++) printf("%d",num[j]);
printf("%d",num[i]+);
for(int j=i+;j<len;j++) printf("%d",num[j]);
return ;
}
printf("");
for(int i=;i<len;i++) printf("%d",num[i]);
return ;
}
}

T3 逆序对(pair)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK最近在研究逆序对。

这个问题是这样的。

一开始LYK有一个2^n长度的数组ai。

LYK有Q次操作,每次操作都有一个参数k。表示每连续2^k长度作为一个小组。假设n=4,k=2,则a[1],a[2],a[3],a[4]为一个小组,a[5],a[6],a[7],a[8]为一个小组,a[9],a[10],a[11],a[12]为一个小组,a[13],a[14],a[15],a[16]也为一个小组。

然后LYK对于每个小组都翻转,也就是说原数组会变成a[4],a[3],a[2],a[1],a[8],a[7],a[6],a[5],a[12],a[11],a[10],a[9],a[16],a[15],a[14],a[13]。之后它想求出这2^n个数的逆序对是多少。

因此你需要输出对于每次操作,操作完后这2^n个数的逆序对有多少对。

两个数ai,aj被称为逆序对当且仅当i<j且ai>aj。

输入格式(pair.in)

第一行一个数n。

接下来一行2^n个数ai表示一开始的数组。

接下来一行一个数Q,表示操作的次数。

接下来一行Q个数,表示每次操作的参数k。

输出格式(pair.out)

Q行,表示每次操作后的答案。

输入样例

2

2 1 4 3

4

1 2 0 2

输出样例

0

6

6

0

样例解释

第一次操作,{2,1,4,3}->{1,2,3,4}

第二次操作,{1,2,3,4}->{4,3,2,1}

第三次操作,{4,3,2,1}->{4,3,2,1}

第四次操作,{4,3,2,1}->{1,2,3,4}

对于30%的数据n<=10,Q<=10。

对于50%的数据n<=10,Q<=1000。

对于80%的数据n<=10,Q<=200000。

对于100%的数据n<=17,Q<=200000,1<=ai<=2^n。

例:1 2 3 4 5 6 7 8  k=3

翻转结果为 8 7 6 5 4 3 2 1

将翻转过程拆分:

第一步: 2 1 4 3 6 5 8 7

第二步:4 3 2 1 8 7 6 5

第三步:8 7 6 5 4 3 2 1

所以每一次翻转都可以拆分,而拆分的过程就是交换相邻的2^(步数-1)

所以归并排序求逆序对的时候,用st表维护从第i个位置,长为2^j的区间的逆序对个数

然后求出对应区间的顺序对个数

维护所有长为2^i的区间的逆序对个数rev[i]和顺序对个数pos[i]

统计答案的时候,拆分就是swap(rev,pos)

在这里顺序对个数是用总个数-逆序对个数求的

所以就会有一个问题,例:

2 2 3 3

实际上的:

pos : 0  0

rev :  0  0

但求的时候,pos :2  4

因为用总个数-逆序对个数=顺序对个数+相等的数对

所以归并过程中,还要预处理从第i个位置,长为2^j的区间的相等数对个数

计算rev,pos时,同时计算same[i],表示所有长为2^i的区间相等的数对个数

求解的时候 先swap(rev,pos),然后rev-=same,再 pos=总的-rev

#include<cstdio>
#include<iostream>
#include<algorithm> #define N 17
//#define M 1<<N using namespace std; typedef long long LL; const int M=<<; int n,tot;
int a[M+],res[M+],bit[M+],P[M+];
LL st[M+][N+],ST[M+][N+];
LL rev[N+],pos[N+],same[N+],sum[N+]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void gbsort(int l,int r)
{
if(l==r) return;
int mid=l+r>>;
gbsort(l,mid);
gbsort(mid+,r);
for(int p=r;p>=l;--p) P[p]=p;
for(int p=r-;p>=l;--p)
if(a[p]==a[p+]) P[p]=P[p+];
int i=l,j=mid+,k=l;
while(i<=mid && j<=r)
{
if(a[i]>a[j]) st[l][bit[r-l+]]+=mid-i+,res[k++]=a[j++];
else if(a[i]==a[j]) ST[l][bit[r-l+]]+=P[j]-j+,res[k++]=a[i++];
else res[k++]=a[i++];
}
while(i<=mid) res[k++]=a[i++];
while(j<=r) res[k++]=a[j++];
for(k=l;k<=r;++k) a[k]=res[k];
} void pre()
{
for(int i=;i<=n;++i) sum[i]=1ll*(<<i-)*(<<i-);
for(int i=,len=;i<=n;++i,len<<=)
for(int j=;j<=tot;j+=len)
rev[i]+=st[j][i],pos[i]+=sum[i]-st[j][i],same[i]+=ST[j][i];
} int main()
{
freopen("pair.in","r",stdin);
freopen("pair.out","w",stdout);
read(n); tot=<<n;
for(int i=;i<=tot;++i) bit[i]=bit[i>>]+;
for(int i=;i<=tot;++i) read(a[i]);
gbsort(,tot);
pre();
int m,k; read(m);
LL ans;
while(m--)
{
read(k);ans=;
for(int i=;i<=k;++i) swap(rev[i],pos[i]),rev[i]-=same[i],pos[i]=sum[i]*tot/(<<i)-rev[i];
for(int i=;i<=n;++i) ans+=rev[i];
printf("%I64d\n",ans);
}
return ;
}

考场上40分暴力也打炸了

1、归并排序最后没有for(k=l;k<=r;k++) a[k]=res[k];

2、归并排序后数组变为有序,下一次操作前没有还原

3、输入n,元素有1<<n个,全用的n

暴力:

#include<cstdio>
#include<iostream>
#define N 131073
using namespace std;
typedef long long LL;
int a[N],tot,res[N],t[N];
LL ans;
inline void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void reverse(int k)
{
int len=<<k,tmp=len>>;
for(int i=;i<=tot;i+=len)
{
for(int j=;j<=tmp;j++)
swap(a[j+i-],a[len-j++i-]);
}
}
void gbsort(int l,int r)
{
if(l==r) return;
int mid=l+r>>;
gbsort(l,mid);
gbsort(mid+,r);
int i=l,j=mid+,k=l;
while(i<=mid && j<=r)
{
if(a[i]>a[j]) { ans+=mid-i+; res[k++]=a[j++]; }
else res[k++]=a[i++];
}
while(i<=mid) res[k++]=a[i++];
while(j<=r) res[k++]=a[j++];
for(k=l;k<=r;k++) a[k]=res[k];
}
void out(long long x)
{
if(x/) out(x/);
putchar(x%+'');
}
int main()
{
freopen("pair.in","r",stdin);
freopen("pair.out","w",stdout);
int n; read(n);
tot=<<n;
for(int i=;i<=tot;i++) read(a[i]);
int q,k;
read(q);
while(q--)
{
read(k);
reverse(k);
for(int i=;i<=tot;i++) t[i]=a[i];
ans=;
gbsort(,tot);
for(int i=;i<=tot;i++) a[i]=t[i];
out(ans);
printf("\n");
}
fclose(stdin); fclose(stdout);
return ;
}

2017北京国庆刷题Day2 morning的更多相关文章

  1. 2017北京国庆刷题Day2 afternoon

    期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一 ...

  2. 2017北京国庆刷题Day1 afternoon

    期望得分:100+100+100=300 实际得分:100+100+100=300 T1 一道图论好题(graph) Time Limit:1000ms   Memory Limit:128MB 题目 ...

  3. 2017北京国庆刷题Day7 morning

    期望得分:100+0+100=200 实际得分:100+20+0=120 离散化搞搞 #include<cstdio> #include<iostream> #include& ...

  4. 2017北京国庆刷题Day5 afternoon

    期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)… ...

  5. 2017北京国庆刷题Day3 morning

    期望得分:100+60+0=160 实际得分:100+30+0=130 考场上用的哈希 #include<cstdio> #include<cstring> #include& ...

  6. 2017北京国庆刷题Day4 morning

    期望得分:0+40+30=70 实际得分:0+10+10=20 题目修改:只能由0变1,只能用一次操作 大模拟 #include<cstdio> #include<cstring&g ...

  7. 2017北京国庆刷题Day5 morning

    期望得分:0+60+60=120 实际得分:0+30+60=90 令g=gcd(X11,X12,X13……) 则行列式可能为D的充要条件为g|D 1.g|D为必要条件: 由定义来算行列式的时候,每一项 ...

  8. 2017北京国庆刷题Day4 afternoon

    期望得分:100+100+0=200 实际得分:5+0+0=5 每加入一个数,x的因数位置++ 注意:根号x枚举时,如果x是完全平方数,根号x会重复累计2次,要减去 考场上没减,5分 /(ㄒoㄒ)/~ ...

  9. 2017北京国庆刷题Day6 afternoon

    期望得分:100+100+40=240 实际得分:100+0+40=140 二进制拆分.二进制前缀和 #include<cstdio> #include<iostream> u ...

随机推荐

  1. MySort试验记录

    MySort试验记录 编写目标 结果代码 思路 将数组每一个项目的第三组数字抽出来并且排序成12345的顺序,并形成新数组k3. 把原数组的每一项与k3进行比较,每符合一项便输出一项,从而重新排序出新 ...

  2. 2018软工实践—Alpha冲刺(8)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 多次测试软件运行 学习OPENMP ...

  3. mysql hql异常

    org.springframework.dao.InvalidDataAccessResourceUsageException:  could not execute query; nested ex ...

  4. OA_1界面

    <%@ page language="java" contentType="text/html;charset=GB18030" pageEncoding ...

  5. UVALive 6913 I Want That Cake 博弈+dp

    题目链接: http://acm.hust.edu.cn/vjudge/problem/96343 I Want That Cake Time Limit: 3000MS 64bit IO Forma ...

  6. css3 伪元素 ::before ::after

    键代码分析: /*css代码*/ .effect::before, .effect::after{ content:""; position:absolute; z-index:- ...

  7. jQuery之offset,position

    获取/设置标签的位置数据 * offset(): 相对页面左上角的坐标 * position(): 相对于父元素左上角的坐标. 需求: 1. 点击 btn1 打印 div1 相对于页面左上角的位置 打 ...

  8. 解决Max retries exceeded with url的问题

    requests.exceptions.ConnectionError: HTTPSConnectionPool(host='itunes.apple.com', port=443): Max ret ...

  9. 敏捷冲刺DAY4

    一. 每日会议 1. 照片 2. 昨日完成工作 登录界面的进一步完善 服务器搭建 建立数据库 3. 今日完成工作 发布和提供需求功能的实现 用户修改自己的信息 用户界面设计 管理员界面设计 4. 工作 ...

  10. PSP 进度条 柱状图 饼状图

    9号 类别 开始时间 结束时间 间隔 净时间 燃尽图 8::00 8:20 0 20分钟 站立会议 8:20 8:50 0 30分钟 读构建之法 9:20 13:20 120分钟 120分钟 四人小组 ...