队友牛逼!带我超神!蒟蒻的我还是一点一点的整理题吧...

Dragon Ball I

这个题算是比较裸的题目吧....学过图论的大概都知道应该怎么做。题目要求找到七个龙珠的最小距离。很明显就是7个龙珠先后去的排列,然后用dijkstra预处理出来每个龙珠到所有其他的点的最短距离啊。最后dfs暴力枚举排列统计答案就行。这里有一些小的细节问题题目中最大的距离为2e9,所以0x3f可能有点不够,还真是细节决定成败啊,不亏我Wrong了一发!

//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=200010;
int n,m,link[N],id[10],tot,vis[N],d[10][N];
struct bian{ll y,v,next;}a[N<<1];
ll ans=1e18;
priority_queue<pair<ll,int> >q; inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
} inline void add(int x,int y,int v)
{
a[++tot].y=y;a[tot].v=v;a[tot].next=link[x];link[x]=tot;
} inline void dijkstra(int s)
{
rep(i,1,n) d[s][i]=2e9;
memset(vis,0,sizeof(vis));
d[s][id[s]]=0;
q.push({0,id[s]});
while(q.size())
{
int x=q.top().second;q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=link[x];i;i=a[i].next)
{
int y=a[i].y;
if(d[s][y]>d[s][x]+a[i].v)
{
d[s][y]=d[s][x]+a[i].v;
q.push({-d[s][y],y});
}
}
}
} inline void dfs(int now,int cnt,ll s)
{
if(cnt==7)
{
ans=min(ans,s);
return;
}
rep(i,1,7)
{
if(!vis[i])
{
vis[i]=1;
dfs(i,cnt+1,s+d[now][id[i]]);
vis[i]=0;
}
}
} int main()
{
//freopen("1.in","r",stdin);
get(n);get(m);
rep(i,1,m)
{
int get(x),get(y),get(v);
add(x,y,v);add(y,x,v);
}
id[0]=1;
rep(i,1,7) get(id[i]);
rep(i,0,7) dijkstra(i);
rep(i,1,7)
{
if(d[0][id[i]]==2e9)
{
puts("-1");
return 0;
}
}
memset(vis,0,sizeof(vis));
dfs(0,0,0);
putl(ans);
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.

Farming Mars

这个算是比较裸的数据结构的题了...简化下题意就是:给你一个序列,有询问,问一个区间中有没有一个数的个数大于等于区间的一半(向上取整).先不想那么多,看到10000的范围,我这暴脾气,先打个暴力试试,\(O(n^2)\)闯天下啊,真过了,赛后就不能这样敷衍了事了。仔细想想不就是权值计数吗?区间查询最大值,写个主席树不就行了?...太水了题...不对不对,这不太行啊,主席树没法维护区间最大值啊...假了假了假了...原来小丑竟是我自己...等等等..等等,这个题问的不是区间众数的次数吗?分块啊!还是分块大法好!莫队!所有\(O(n\sqrt n)\)的数据结构都行。

先放个暴力的代码:

//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=10010;
int n,m,a[N],ct[N],num;
db b[N],t[N]; inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
} inline int find(db s) {return lower_bound(b+1,b+num+1,s)-b;} inline void init()
{
get(n);get(m);
rep(i,1,n) cin>>t[i],b[i]=t[i];
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
rep(i,1,n) a[i]=find(t[i]);
} int main()
{
//freopen("1.in","r",stdin);
init();
rep(i,1,m)
{
int get(l),get(r);
rep(j,l,r) ct[a[j]]++;
bool flag=false;
rep(j,l,r) if(ct[a[j]]>=((r-l+1)/2)+1)
{
flag=true;
break;
}
if(flag) puts("usable");
else puts("unusable");
rep(j,l,r) ct[a[j]]=0;
}
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.

回滚莫队的代码,分块由于前不久练过,就不再写一遍了,真的很费脑细胞...

//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=10010;
int a[N],num,n,m,ans[N];
int belong[N],bl[N],br[N],block,bnum,cnt1[N],cnt2[N];
db t[N],b[N];
struct wy{int l,r,id;}q[N]; inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
} inline int find(db s) {return lower_bound(b+1,b+num+1,s)-b;} inline void build()
{
block=sqrt(n);bnum=n/block;
if(n%block) bnum++;
rep(i,1,n) belong[i]=(i-1)/block+1;
rep(i,1,bnum) bl[i]=(i-1)*block+1,br[i]=i*block;
br[bnum]=n;
} inline bool cmp(wy a,wy b)
{
return (belong[a.l]!=belong[b.l]?belong[a.l]<belong[b.l]:a.r<b.r);
} inline void init()
{
get(n);get(m);
rep(i,1,n) cin>>t[i],b[i]=t[i];
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
rep(i,1,n) a[i]=find(t[i]);
rep(i,1,m) get(q[i].l),get(q[i].r),q[i].id=i;
build();
sort(q+1,q+m+1,cmp);
} inline void solve()
{
int i=1;
rep(j,1,bnum)
{
int now=0;
int l=br[j]+1,r=br[j];
memset(cnt1,0,sizeof(cnt1));
for(;i<=m&&belong[q[i].l]==j;++i)
{
int temp;
int ql=q[i].l,qr=q[i].r;
if(belong[ql]==belong[qr])
{
temp=0;
rep(k,ql,qr) cnt2[a[k]]=0;
rep(k,ql,qr) cnt2[a[k]]++,temp=max(temp,cnt2[a[k]]);
ans[q[i].id]=(temp>=(qr-ql+1)/2+1?1:0);continue;
}
while(r<qr) cnt1[a[++r]]++,now=max(now,cnt1[a[r]]);
temp=now;
while(l>ql) cnt1[a[--l]]++,now=max(now,cnt1[a[l]]);
ans[q[i].id]=(now>=(qr-ql+1)/2+1?1:0);
now=temp;
while(l<br[j]+1) cnt1[a[l++]]--;
}
}
rep(i,1,m)
{
if(ans[i]) puts("usable");
else puts("unusable");
}
} int main()
{
// freopen("1.in","r",stdin);
init();
solve();
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.

Sum and Product

队友牛逼带我超神....

首次看这个题,题意很好理解就是找到有多少个子区间,使得这个区间里所有元素的乘积等于和。...

看起来好复杂...但仔细思考一下,全部元素的乘积,...,这玩意是不是有点大....连续64个2想乘就爆longlong了,那全部元素的和的大小范围呢?\(n\)是\(2e5\),\(a_i\)是\(1e9\),也就是说这里的元素和最大值为\(2e14\),那乘积超过这个不就一定不合法了吗?那直接暴力,然后break。T了....为啥会T啊...昂,对了序列中可能有很多的1使得乘积长时间不变,那我们考虑能不能直接跳过这些乘积,直接和有效的数组想乘,我这里记了一个id[i]数组表示i之后一个非1的位置,然后固定左端点,寻找去合法右端点的数目,由于中间全部是1,累乘的结果很好维护,累加的话根据下标计算也很容易。考虑这之间有没有可能会出现合法的右端点,由于全部是1,所以乘积不变,和一直加,若之前和<乘积。并且这里1的个数又足够多的话,我们就能在一堆1中实现和=积的情况,并且最多一次,因为相等之后,和还往上加,积就不变,一定不和法,那这样就好办了,我们在跳的一堆1中看有没有符合条件的,跳过后看有没有符合条件。这样最多跳64次。总复杂度为\(O(nlogn)\)

注意这里用除法代替乘法,避免爆long long.

//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=2e5+10;
const ll MAX=2e14;
int n,a[N],id[N],now; inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
} int main()
{
//freopen("1.in","r",stdin);
get(n);
rep(i,1,n) get(a[i]);
int now=n;
fep(i,n,1)
{
id[i]=now;
if(a[i]!=1) now=i;
}
id[n]=0;
int ans=0;
rep(i,1,n) //统计每个左端点合法的右端点
{
ll mt=a[i],sm=a[i];
now=i;
while(id[now])
{
if(MAX/mt<a[id[now]]) break;
if(sm<mt&&sm+(id[now]-now-1)>=mt) ++ans;
mt=mt*a[id[now]];
sm=sm+a[id[now]]+(id[now]-now-1);
if(mt==sm) ++ans;
now=id[now];
}
}
put(ans);
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.

J True/False Worksheet

这个题主要是思路被限制住了,想到并查集后就完全想着用数学方法解决问题了...

其实看到\(n\)为\(5000\)的时候就可以考虑\(dp\)的写法了。

首先考虑无解的情况,就是一个要求不相同的区间里面的数被迫相同,我们直接预处理就行。

考虑\(DP\)怎样设状态,由于题目中的限制条件是一个区间必须是相同或不能全部相同,所以我们状态中就应该能体现这个相同与否的状态。考虑设\(f[i][j]\)表示从第\(j\)位到第\(i\)位都相同,且到\(i\)位结尾的方案数。转移时可以想不用考虑限制条件。当第\(i\)个和第\(i-1\)个保持一样时\(f[i][j]=f[i-1][j]\),当第\(i\)个和\(i-1\)不一样时,\(f[i][i]=\)\(\sum_{k=1}^{i-1}{f[i-1][k]}\)。那么接下来考虑相同的限制条件,比如说从l到i都必须是相同的,那么\(f[i][1],f[i][2]...f[i][l]\)都是合法的状态,考虑不相同的限制条件,比如从l到i都不相同,那么从\(f[i][l+1],f[i][l+2],...,f[i][i]\)都是合法的,既然如此我们就可以得知每个i的所有合法状态有哪些即\(diff[i]+1-same[i]\)这些状态是合法的。至于当\(f[i][i]\)转移时我们可以对\(i-1\)的转态枚举时,可以直接从\(1\)到\(i-1\),因为在\(i-1\)时我们只保存了合法的状态。同理在统计答案时,我们可以直接求和,不必在乎是否合法,因为我们只保存了合法的状态的值,能转移过来的一定是合法的。

//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=5010;
int n,m,f[N][N];//f[i][j]表示从j到i都相同的方案数
int same[N],diff[N];
bool flag=true;
char c[N]; inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
} inline void init()
{
get(n);get(m);
rep(i,1,n) same[i]=i;
rep(i,1,m)
{
int get(x),get(y);
scanf("%s",c+1);
if(c[1]=='s') same[y]=min(same[y],x);
else diff[y]=max(diff[y],x);
}
rep(i,1,n) if(diff[i]>=same[i]) flag=false;
if(!flag) puts("0");
} inline void solve()
{
f[1][1]=2;
rep(i,2,n)
{
rep(j,diff[i]+1,same[i]) f[i][j]=(f[i][j]+f[i-1][j])%P;
if(same[i]==i)
{
rep(j,1,i-1) f[i][i]=(f[i][i]+f[i-1][j])%P;
}
}
int ans=0;
rep(i,1,n) ans=(ans+f[n][i])%P;
put(ans);
} int main()
{
//freopen("1.in","r",stdin);
init();
if(flag) solve();
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.

ICPC Mid-Central USA Region 2019 题解的更多相关文章

  1. 2016 ICPC Mid-Central USA Region J. Windy Path (贪心)

    比赛链接:2016 ICPC Mid-Central USA Region 题目链接:Windy Path Description Consider following along the path ...

  2. ICPC North Central NA Contest 2018

    目录 ICPC North Central NA Contest 2018 1. 题目分析 2. 题解 A.Pokegene B.Maximum Subarrays C.Rational Ratio ...

  3. Hello 2019题解

    Hello 2019题解 题解 CF1097A [Gennady and a Card Game] map大法好qwq 枚举每一个的第\(1,2\)位判是否与给定的重复即可 # include < ...

  4. ICPC World Finals 2019 题解

    [A]Azulejos 题意简述: 有两排瓷砖,每排都有 \(n\) 个,每个瓷砖有高度 \(h_i\) 和价格 \(p_i\) 两种属性. 你需要分别重新排列这两排瓷砖,使得同一排的瓷砖满足价格不降 ...

  5. Code Chef February Challenge 2019题解

    传送门 \(HMAPPY2\) 咕 话说这题居然卡\(scanf\)的么??? int T;cin>>T; while(T--){ cin>>n>>a>> ...

  6. CodeChef March Challenge 2019题解

    传送门 \(CHNUM\) 显然正数一组,负数一组 for(int T=read();T;--T){ n=read(),c=d=0; fp(i,1,n)x=read(),x>0?++c:++d; ...

  7. 2016ACM/ICPC亚洲区大连站现场赛题解报告(转)

    http://blog.csdn.net/queuelovestack/article/details/53055418 下午重现了一下大连赛区的比赛,感觉有点神奇,重现时居然改了现场赛的数据范围,原 ...

  8. Code Chef January Challenge 2019题解

    传送门 \(div2\)那几道题不来做了太水了-- \(DPAIRS\) 一个显然合法的方案:\(A\)最小的和\(B\)所有连,\(A\)剩下的和\(B\)最大的连 算了咕上瘾了,咕咕咕 const ...

  9. CodeChef April Challenge 2019题解

    传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...

随机推荐

  1. 数据结构逆向分析-Vector

    数据结构逆向分析-Vector 这个应该是家喻户晓了的东西把,如果说C/C++程序员Vector都不用的话,可能就是一个不太好的程序员. Vector就是一个STL封装的动态数组,数组大家都知道是通过 ...

  2. Apache设置禁止访问网站目录

    使用Apache作为Web服务器的时候,在当前目录下没有index.html|php等入口就会显示目录.让目录暴露在外面是非常危险的事. 找到Apache的配置文件 /etc/apache2/apac ...

  3. 监控linux服务器工具nmon的使用

    做压测时,需要查看服务器中的cpu.内存变化,但由于服务器是linux环境,则需要监控linux服务器的工具,下面用到的工具是nmon. 1.安装nmon.在网上下载nmon安装包,在linux服务器 ...

  4. 51nod1355-斐波那契的最小公倍数【min-max容斥】

    正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1355 题目大意 定义\(f_i\)表示斐波那契的第\(i\)项,给出一个 ...

  5. requests之POST请求

    上一节我们讲了GET请求,今天我们来讲讲POST请求. 学习一个新的模块,其实不用去百度什么的,直接用 help 函数就能查看相关注释和案例内容.如图所示,就是我们今天需要学习的内容. 1.用上面给的 ...

  6. Python列表操作常用API

    1.列表的概念 (1)列表的定义 列表是Python中一种基本的数据结构.列表存储的数据,我们称为元素.在列表中的每个元素都会有一个下标来与之对应,第一个索引是0,第二个索引是1,依此类推的整数. 列 ...

  7. 前段---css

    css主要是用来做如何显示html元素的 当浏览器读到一个样式表,它就会按照这个样式表来对文档做渲染 注意:每一个css样式表都是由两个部分组成的, 1,选择器 2,声明 声明又包括属性值和属性,每个 ...

  8. bzoj2038 小z的袜子 (莫队)

    题目大意 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只袜子从1到N编 ...

  9. 最新.NET MAUI有什么惊喜?

    .NET 6 Preview 7 现已发布啦,我们为 .NET 多平台应用程序 UI (MAUI) 引入了所有的新布局.这是性能和可靠性的重大变化.我们很高兴我们还增加了一些关于accessibili ...

  10. 初探JavaScript PDF blob转换为Word docx方法

    PDF转WORD为什么是历史难题 PDF 转Word 是一个非常非常普遍的需求,可谓人人忌危,为什么如此普遍的需求,却如此难行呢,还得看为什么会有这样的一个需求: PDF文档遵循iOS32000的规范 ...