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

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. 使用manacher算法解决最长回文子串问题

    要解决的问题 求一个字符串最长回文子串是什么.且时间复杂度 O(N) 具体描述可参考: LeetCode_5_最长回文子串 LintCode_200_最长回文子串 暴力解法 以每个字符为中心向左右两边 ...

  2. 【PHP数据结构】链表的相关逻辑操作

    链表的操作相对顺序表(数组)来说就复杂了许多.因为 PHP 确实已经为我们解决了很多数组操作上的问题,所以我们可以很方便的操作数组,也就不用为数组定义很多的逻辑操作.比如在 C 中,数组是有长度限制的 ...

  3. 深入学习Composer原理(二)

    本系列的第二篇文章,这次我们聊聊:spl_autoload_register()函数 PHP的SPL库作为扩展库,已经于5.3.0版本后默认保持开启,成为PHP的一组强大的核心扩展库.大家有时间可以多 ...

  4. 深入学习Composer原理(一)

    Composer作为PHP的包管理工具,为PHPer们提供了丰富的类库,并且让PHP重焕新生,避免被时代淘汰的悲剧.可以说,Composer和PHP7是现在PHP开发者的标配,如果你还没用过Compo ...

  5. 微信小程序 创建自己的第一个小程序

    * 成为微信公众平台的开发者 注册 https://mp.weixin.qq.com * 登录 https://open.weixin.qq.com/ * 开发者工具下载 https://develo ...

  6. 使用form插件 和ajax 结合使用 没有调用success的原因

    当我做文件上传的时候出现不调用success方法  将datype: 'json' 注释掉后成功响应 浏览器显示200状态码,并且响应头为json格式,格式ajax不认为它是json,所以一直执行错误 ...

  7. P3649-[APIO2014]回文串【PAM】

    正题 题目链接:https://www.luogu.com.cn/problem/P3649 题目大意 一个字符串,求最大的回文串长度×出现次数 解题思路 构建出\(\text{PAM}\)然后统计一 ...

  8. P3308-[SDOI2014]LIS【最小割】

    正题 题目链接:https://www.luogu.com.cn/problem/P3308 题目大意 三个\(n\)个数字的序列\(A,B,C\).要求删除其中某些位置\(i\)使得\(A\)的最长 ...

  9. 服务器使用matplotlib绘图

    Two points: 1. change backend of matplotlib: import matplotlib.pyplot as plt plt.switch_backend('agg ...

  10. 浏览器输入URL之后,HTTP请求返回的完整过程

    1.输入url,按下回车时,先做一个redirect(重定向),因为浏览器可能记录本机的地址已经永久跳转成新的地址,所以一开始浏览器就先要判断下需不需要重定向,以及重定向到哪里:2.然后第二步就是看A ...