期望得分: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. git中的重要指令

    git命令 任何操作都需要以 git 命令为开头 本地操作: git init 初始化一个本地仓库 新建为 master主分支 git status 查看当前分支状态 git add <文件名& ...

  2. 学习调用第三方的WebService服务

    互联网上面有很多的免费webService服务,我们可以调用这些免费的WebService服务,将一些其他网站的内容信息集成到我们的应用中显示,下面就以查询国内手机号码归属地为例进行说明. 首先安利一 ...

  3. plsql 永久注册码

    注册码:Product Code:4t46t6vydkvsxekkvf3fjnpzy5wbuhphqzserial Number:601769 password:xs374ca 可用

  4. 模拟登入教务处(header)

    import HTMLParser import urlparse import urllib import urllib2 import cookielib import string import ...

  5. 《我是一只it小小鸟》观后感

    在这个学期开始的时候我们的老师推荐给我们这本书.在很多的网站上只要一提到IT,总会有人推荐这本书,我在读这本书之前看了很多关于它的书评,其中有一位网友的一句话让我对它产生了很大的兴趣:“印象最深的是书 ...

  6. 倒计时60s 代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 更改HTTP头信息

    http信息分三部分 1.请求行 GET  lizi.php  HTTP/1.1 2.HTTP头信 Host: localhost Connection: keep-alive Cache-Contr ...

  8. PHP开发工具(CodeLobster PHP Edition)

    参考:http://www.uzzf.com/soft/45948.html 产品名:ttrar.com 密    钥:dstp-187c-9cdd-9a60-e185-b280 CodeLobste ...

  9. 【C++】深度探索C++对象模型读书笔记--构造函数语义学(The Semantics of constructors)(四)

    成员们的初始化队伍(member Initia 有四种情况必须使用member initialization list: 1. 当初始化一个reference member时: 2. 当初始化一个co ...

  10. LDPC译码器的FPGA实现

    应用笔记 V0.0 2015/3/17 LDPC译码器的FPGA实现   概述   本文将介绍LDPC译码器的FPGA实现,译码器设计对应CCSDS131x1o1s文档中提到的适用于深空通信任务的LD ...