一道图论神题(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

思路:贪心,一遍AC。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define MAXN 101000
using namespace std;
map<int,int>ma[MAXN];
int n,m,tot,cap[MAXN];
long long ans;
int to[MAXN*],net[MAXN*],head[MAXN*];
struct nond{
int val,id;
}v[MAXN];
int cmp(nond a,nond b){
return a.val>b.val;
}
void add(int u,int v){
to[++tot]=v;net[tot]=head[u];head[u]=tot;
to[++tot]=u;net[tot]=head[v];head[v]=tot;
}
int main(){
freopen("god.in","r",stdin);
freopen("god.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&v[i].val);
v[i].id=i;
cap[i]=v[i].val;
}
sort(v+,v++n,cmp);
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
ma[u][v]=;
ma[v][u]=;
}
for(int i=;i<=n;i++){
for(int j=head[v[i].id];j;j=net[j])
if(ma[v[i].id].find(to[j])!=ma[v[i].id].end()){
ans+=cap[to[j]];
ma[to[j]].erase(v[i].id);
}
}
cout<<ans;
}
/*
4 3
10 20 30 40
1 4
1 2
2 3
*/

位运算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。

思路:大模拟,有三种情况没有考虑,挂掉了3个点。

~~~~(>_<)~~~~ 改不过来了90分代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char n[];
int len;
int num[],tmp[],ans[];
int main(){
freopen("bit.in","r",stdin);
freopen("bit.out","w",stdout);
int cnt=,flag=,flag1=;
scanf("%s",n);
len=strlen(n);
if(n[]!='-'){
for(int i=;i<len;i++){
num[i+]=n[i]-'';
tmp[i+]=num[i+];
}
if(len!=){
if(num[len]<=&&num[len-]>=){
int y=;
num[len-]-=;num[len]+=;
while(num[y]==) y++;
for(int i=y;i<=len;i++) cout<<num[i];
return ;
}
else if(num[len]>&&num[len-]>=){
if(num[len-]!=){
int bns=-num[len-]-,y=;
num[len-]-=;
num[len-]=;
num[len]-=bns;
while(num[y]==) y++;
for(int i=y;i<=len;i++) ans[++cnt]=num[i];
}
else{
int x=,y=;
int bns=-num[len-]-;
while(!num[len-x]&&len!=) x++;
num[len-x]-=;
num[len-x+]=;
num[len-x+]=num[len]-bns;
while(num[y]==) y++;
for(int i=y;i<=len-x+;i++) ans[++cnt]=num[i];
for(int i=len-x+;i<=len;i++) ans[++cnt]=;
}
for(int i=;i<=cnt;i++)
if(ans[i]>=||ans[i]<) flag=;
if(len==cnt)
for(int i=;i<=cnt;i++)
if(ans[i]>tmp[i]){
flag=;
break;
}
else if(ans[i]<tmp[i])
break;
if(flag){
cout<<"-";
for(int i=len;i>=;i--)
if(tmp[i]!=){
flag1=;
tmp[i]+=;
break;
}
if(!flag1) tmp[]+=;
}
if(!flag) for(int i=;i<=len;i++) cout<<ans[i];
if(flag&&flag1) for(int i=;i<=len;i++) cout<<tmp[i];
else if(flag&&!flag) for(int i=;i<=len;i++) cout<<tmp[i];
return ;
}
else if(num[len]<=&&num[len-]<){
int x=,y=;
while(!num[len-x]) x++;
num[len-x]-=;
num[len-x+]=num[len]+;
while(num[y]==) y++;
for(int i=;i<=len-x+;i++) cout<<num[i];
for(int i=len-x+;i<=len;i++) cout<<"";
return ;
}
}
else{
cout<<"-"<<num[]+;
return ;
}
}
else{
len-=;
for(int i=;i<=len;i++){
num[i]=n[i]-'';
tmp[i]=num[i];
}
for(int i=len;i>=;i--)
if(tmp[i]!=){
flag1=;
tmp[i]+=;
break;
}
if(!flag1) tmp[]+=;
cout<<"-";
if(flag1) for(int i=;i<=len;i++) cout<<tmp[i];
else for(int i=;i<=len;i++) cout<<tmp[i];
return ;
}
}

这是标程:

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
char s[];
int len,sum,i,j,FLAG;
int main()
{
freopen("bit.in","r",stdin);
freopen("bit.out","w",stdout);
scanf("%s",s); FLAG=;
if (s[]!='-')
{
len=strlen(s); sum=;
for (i=len-; i>=; i--)
{
if (s[i]>='' && sum>=)
{
s[i]=char(s[i]-);
sum=;
for (j=i+; j<len; j++)
{
while (sum && s[j]<'')
{
sum--;
s[j]=char(s[j]+);
}
}
int SS=;
for (j=i+; j<len; j++) SS+=s[j]-'';
for (j=i+; j<len; j++)
{
if (SS>=) {s[j]=''; SS-=;} else {s[j]=char(SS+''); SS=;}
}
FLAG=;
break;
}
sum+=''-s[i];
}
if (FLAG)
{
for (i=; i<len; i++) if (s[i]!='') break;
for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
return ;
}
cout<<'-';
for (i=len-; i>=; i--)
{
if (s[i]<'')
{
s[i]=char(s[i]+);
FLAG=;
break;
}
}
if (FLAG)
{
for (i=; i<len; i++) if (s[i]!='') break;
for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
return ;
}
cout<<;
for (i=; i<len; i++) if (s[i]!='') break;
for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
return ;
} FLAG=;
cout<<'-';
len=strlen(s);
for (i=len-; i>=; i--)
{
if (s[i]<'')
{
s[i]=char(s[i]+);
FLAG=;
break;
}
}
if (FLAG)
{
for (i=; i<len; i++) if (s[i]!='') break;
for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
return ;
}
cout<<;
for (i=; i<len; i++) if (s[i]!='') break;
for (j=min(len-,i); j<len; j++) cout<<s[j]; cout<<endl;
return ;
}

逆序对(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<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=(<<)+;
int n,T,PP,now,A,sum,o;
int p[N],a[N],b[N],RR[N];
long long t[],TT[];
long long st[N][],ST[N][];
void pre(int l,int r){
if(l==r) return;
int mid=(l+r)/;
pre(l,mid);
pre(mid+,r);
int i=l,j=mid+,o=l;
for(i=l;i<=r;i++) b[i]=a[i];
for(i=r;i>=mid;i--){
RR[i]=i;
if(i!=r&&b[i+]==b[i])
RR[i]=RR[i+];
}
i=l;j=mid+;
while(i<=mid&&j<=r){
if(b[i]<=b[j]){
a[o++]=b[i];
if(b[i]==b[j])
ST[l][p[r-l+]]+=RR[j]-j+;
i++;
}
else{
a[o++]=b[j];
st[l][p[r-l+]]+=mid-i+;
j++;
}
}
if(i<=mid)
for(j=i;j<=mid;j++) a[o++]=b[j];
else if(j<=r)
for(i=j;i<=r;i++) a[o++]=b[i];
}
int main(){
freopen("pair.in","r",stdin);
freopen("pair.out","w",stdout);
scanf("%d",&n);
sum=(<<n);
for(int i=;i<=sum;i++) scanf("%d",&a[i]);
for(int i=;i<=;i++) p[<<i]=i;
pre(,sum);
for(int i=;i<=n;i++)
for(int j=;j<=(<<n);j+=(<<i)){
t[i]+=st[j][i];
TT[i]+=ST[j][i];
}
scanf("%d",&T);
while(T--){
long long ans=;int Q;
scanf("%d",&Q);
for(int i=;i<=Q;i++) t[i]=1ll*(<<i-)*(<<i-)*(<<n-i)-TT[i]-t[i];
for(int i=;i<=n;i++) ans+=t[i];
printf("%I64d\n",ans);
}
return ;
}

国庆 day 2 上午的更多相关文章

  1. 国庆 day 7 上午

    思路:模拟,set记录一下. #include<set> #include<cstdio> #include<cstring> #include<iostre ...

  2. 国庆 day 3 上午

    a[问题描述] 你是能看到第一题的 friends 呢. ——hja 怎么快速记单词呢?也许把单词分类再记单词是个不错的选择.何大爷给 出了一种分单词的方法,何大爷认为两个单词是同一类的当这两个单词的 ...

  3. 国庆 day 6 上午

    1. 角谷猜想(kakutani.pas/c/cpp)(kakutani.in/out)时间限制:1s/空间限制:256M[题目描述] 某个名字末尾是 654321 的小 A 同学是个大家眼中公认的学 ...

  4. 2018国庆YALI集训游记

    想了想,像之前那样简略地叙述题意和做法,根本没讲清楚,没有任何意义,还不如写写自己的感受. 感觉YALI真的是一所挺不错的学校吧.总是能有一机房的julao轮番吊打你,总是能有集训队的奆佬来给你出dl ...

  5. SSH-Struts第三弹:传智播客视频教程第一天上午的笔记

    一. 框架概述1.三大框架 : 是企业主流 JavaEE 开发的一套架构 Struts2 + Spring + Hibernate 2. 什么是框架?为什么要学框架 ?框架 是 实现部分功能的代码 ( ...

  6. JAVA判断当前时间是上午am还是下午pm

    //结果为"0"是上午 结果为"1"是下午 public class GregorianTest { public static void main(Strin ...

  7. PKUSC 模拟赛 day2 上午总结

    今天上午考得不是很好,主要还是自己太弱QAQ 开场第一题给的图和题意不符,搞了半天才知道原来是走日字形的 然后BFS即可 #include<cstdio> #include<cstr ...

  8. PKUSC 模拟赛 day1 上午总结

    思考了一下第二题,觉得有无数种乱搞做法 类似什么bitset压位,MCS染色之类奇怪的做法 然而都是玄学正确性或者玄学复杂度 先放题解把 第一题显然具有单调性,二分就可以啦 O(nlogn),貌似输出 ...

  9. hihoCoder 1041 国庆出游 (DFS)

    题意: 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比较有特色:它共有n座城市(编号1-n):城市之间恰好有n-1条公路相连,形成一个树形公路网.小Hi计划从A国首都(1号城市)出发,自驾遍历 ...

随机推荐

  1. ElasticSearch启动报错,bootstrap checks failed

    修改elasticsearch.yml配置文件,允许外网访问. vim config/elasticsearch.yml# 增加 network.host: 0.0.0.0 启动失败,检查没有通过,报 ...

  2. 集成spring boot + mysql + docker实战

    前言 网上找过很多文章,关于通过docker构建mysql容器并将应用容器和docker容器关联起来的文章不多.本文将给出具体的范例.此处为项目的源码 前置条件 该教程要求在宿主机上配置了: dock ...

  3. S3C6410 LCD Overlay Test Program

    测试了一下S3C6410 LCD控制器提供的Overlay功能,写了一个简单的test,主要用于实现FB0和FB1之间的Overlay操作.内核选项的Windows至少要为2. 具体支持如下操作:1 ...

  4. [using_microsoft_infopath_2010]Chapter1 介绍InfoPath2010

    本章提要 1.列举对于就SharePoint2010来说使用InfoPath2010的好处 2.使用Office后台函数创建InfoPath表单 3.使用InfoPath接口 4.创建基于XML的文件 ...

  5. Python中常见的文件对象内建函数

    文件对象内建方法列表 文件对象的方法 操作 file.close() 关闭文件 file.fileno() 返回文件的描写叙述符(file descriptor.FD,整数值) file.flush( ...

  6. CC2540/CC2541 : Set the Peripheral Being Advertising while It is Being Connected

    There is possible to set your CC254X be scanable when it is in connection. But, based on my test,the ...

  7. Sambaserver搭建

    1. 安装Samba及相关包 $ sudo apt-getinstall samba samba-common smbfspython-glade2system-config-samba 2. 创建共 ...

  8. UBUNTU 16.04 下安装动态链接库方法(使用ln命令可以随意映射动态库,ldd查看缺少的动态库)

    一般先使用ldd 来查看该应用程序缺少什么东西,然后,再根据sudo apt install XXX 去安装相应的动态库. 假如没有对应的库,可以使用: sudo ln -s /usr/lib/lib ...

  9. php+mysql时报错:Unknown column '' in 'field list'解决方案

    答案来源:http://jingyan.baidu.com/article/9f7e7ec05c5ad76f281554ab.html 很多人在用php+MySQL做网站往数据库插入数据时发现如下错误 ...

  10. 前后端分离跨域 关于前后端分离开发环境下的跨域访问问题(angular proxy=>nginx )

    前后端分离后遇到了跨域访问的问题: angular1中使用proxy很麻烦,最后还是失败结束:最后总结3种方法如下: 本人使用的第一种方法,只是开发环境下使用很方便! 1:禁掉谷歌的安全策略(Turn ...