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

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. DFS与DFS迷宫问题

    一天蒜头君掉进了一个迷宫里面,蒜头君想逃出去,可怜的蒜头君连迷宫是否有能逃出去的路都不知道. 看在蒜头君这么可怜的份上,就请聪明的你告诉蒜头君是否有可以逃出去的路. 输入格式 第一行输入两个整数n 和 ...

  2. 【OI技巧】解决cin、cout因输入输出慢而TLE的问题

    语言本身没有问题!! 语言本身没有问题!! 语言本身没有问题!! C++本来的设计就是将输入输出流和C的标准输入输出挂钩在一起,这样就导致cin,cout输入输出前先要将内容放入缓冲区,最后再由cin ...

  3. Django学习day12随堂笔记

    每日测验 """ 1.什么是cookie和session,你能描述一下它们的由来和工作机制吗(切勿糊弄,敷衍了事) 2.django中如何操作cookie和session ...

  4. Django学习day04随堂笔记

    每日测验 """ 今日考题 1.列举你知道的orm数据的增删改查方法 2.表关系如何判定,django orm中如何建立表关系,有什么特点和注意事项 3.请画出完整的dj ...

  5. PHP中环境变量的操作

    在 PHP 中,我们可以通过 phpinfo() 查看到当前系统中的环境变量信息(Environment).在代码中,我们也可以通过两个函数,查看和修改相应的环境变量信息. getenv() 获取环境 ...

  6. Linux系列(31) - rpm命令管理之升级与卸载命令(3)

    升级命令 rpm -Uvh 包全名(要升级到的软件版本),如果没有安装这个软件的任何版本,这个命令可以代替rpm -ivh. rpm -Uvh 包全名 选项: - -U(upgrade):升级 卸载命 ...

  7. python全局变量的定义

    第一:如定义在类或者函数体外,在函数或者类中引用需要用到 global声明 temp_t = "ceshi" def tmp1(): global temp_t temp_t =1 ...

  8. centos查找大文件

    首先到相当的目录下面,按下面方式查找 find . -type f -size +800M  -print0 | xargs -0 ls -lah或者从根目录(/)开始查找find / -type f ...

  9. 如何使用jemeter进行性能测试

    下载链接:http://jmeter.apache.org/download_jmeter.cgi 一:如何使用jemeter进行压测 1)稳定性测试就需要长时间运行,其运行时间1天.2天.一周等 2 ...

  10. 鸿蒙内核源码分析(忍者ninja篇) | 都忍者了能不快吗 | 百篇博客分析OpenHarmony源码 | v61.02

    百篇博客系列篇.本篇为: v61.xx 鸿蒙内核源码分析(忍者ninja篇) | 都忍者了能不快吗 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...