题目:https://codeforces.com/contest/1101
求是k的倍数且不在区间[l,r]里的最小数
#include
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int q;
int main(){
scanf("%d",&q);
while(q--){
ll l,r,k,t;
cin>>l>>r>>k;
if(k<l|| k>r){
cout<<k<<endl;
}else{
t = (r-k)/k;
cout<<k+(t+1)*k<<endl;
}
}
return 0;
}
B题:求[:||||||:] 的最长长度
关键是读题。。。一点要有[::]这四个,然后|||必须在::中间
#include
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
char s[500005];
int a1,a2,a3,a4;
void solve(){
int len = strlen(s+1);
fo(i,1,len){
if(s[i]=='['){
a1 = i;
break;
}
}
if(a1==0){
printf("-1\n");
return;
}
fo(i,a1+1,len){
if(s[i]==':'){
a2 = i;
break;
}
}
if(a2==0){
printf("-1\n");
return;
}
for(int i=len; i>a2; i--){
if(s[i]==']'){
a4 = i;
break;
}
}
if(a4==0){
printf("-1\n");
return;
}
for(int i=a4-1; i>a2; i--){
if(s[i]==':'){
a3 = i;
break;
}
}
if(a3==0){
printf("-1\n");
return;
}
ll ans = 4;
fo(i,a2+1,a3-1){
if(s[i]=='|')ans++;
}
cout<<ans<<endl;
}
int main(){
scanf("%s",s+1);
solve();
return 0;
}
题意,给n个区间,[l,r]要求把这n个区间分别放到两个集合里
如果区间有交集则必须放在同一个集合,要求两个集合都必须有区间(否则输出0)
输出每个区间所在集合
#include
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
struct node{
int l, r, idx;
bool operator < (const node &p)const{
return l<p.l;
}
}a[200005];
int t,n,ans[200005];
void solve(){
sort(a+1,a+1+n);
int lmx=0,rmx=0;
bool flag = 1, t1=0, t2=0;
fo(i,1,n){
if(a[i].l<=lmx){
lmx = max(lmx, a[i].r);
ans[a[i].idx] = 1;
t1=1;
flag = 0;
}else if(a[i].l<=rmx){
rmx = max(rmx, a[i].r);
ans[a[i].idx] = 2;
t2=1;
flag = 1;
}else if(flag){
t1=1;
ans[a[i].idx] = 1;
lmx = max(lmx, a[i].r);
flag = 0;
}else{
t2=1;
ans[a[i].idx] = 2;
rmx = max(rmx, a[i].r);
flag = 1;
}
}
if(t1&&t2){
fo(i,1,n){
printf("%d ",ans[i]);
}
putchar(10);
}else{
cout<<"-1"<<endl;
}
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
fo(i,1,n){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].idx = i;
}
solve();
}
return 0;
}
题意:在线给出矩形[x,y],在线查询前面给出的矩形能否容纳在矩形[l,r]里(可重叠)输出YES or NO
#include
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n;
ll l,r;
char c;
int main(){
scanf("%d",&n);
ll a1=0,a2=0,b1=0,b2=0; // a表示最长长的矩形的长宽,b表示最长宽的矩形的长宽
getchar();
while(n--){
scanf("%c%lld%lld",&c,&l,&r);
getchar();
if(l<r)swap(l,r);
if(c=='+'){
if(l>=a1){ // 找长最长的矩形
a1=l;
a2=r;
}
if(r>=b1){ // 找宽最长的矩形
b1=r;
b2=l;
}
}else{
// 当无法包含的时候,肯定至少无法包含a,b两个之一
if(a1>l)puts("NO");
else if(a1<=l&&a2>r)puts("NO");
else if(b2>l)puts("NO");
else if(b2<=l&&b1>r)puts("NO");
else puts("YES");
}
}
return 0;
}
看题解,读题也很麻烦
给出一棵树
g(x,y)表示x到y的路径上的点包括(x,y),这整条路径上的数的公约数
要求路径上的点都必须有一个共同的约数
如果不存在一个g(x,y)>1输出0
(因为路径可以是一个点,所以只要有一个数大于1就不是0了,坑!!!)
求这条路径的最长深度
题解:
先预处理出所有质数
然后以分别每个质数nowPri作为约数求出倍数u
以u为一个点进行深索最长的路径(整条路径都必须以nowPri作为约数),更新答案
#include
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 200005;
int n,a[maxn],vis[maxn],dp[maxn],ans;
vector<int> G[maxn],num[maxn],prime;
int cnt,nowPri; // 以nowPri为约数的标记为cnt
void getPrime(){
fo(i,2,maxn-1){
if(vis[i])continue;
prime.push_back(i);
// cout<
for(int j=i; j<maxn; j+=i) vis[j]=1;
}
}
// 寻找约数为nowPri的最长路径
void dfs(int u,int par){
int mx1=0,mx2=0; // 最深子树,次深子树
dp[u]=1;
vis[u]=cnt;
for(int v : G[u]){
if(a[v]%nowPri!=0||v==par)continue; // 不是当前约数的倍数
dfs(v,u);
dp[u] = max(dp[u], 1+dp[v]); // 更新本节点的最大深度
if(dp[v]>=mx1){
mx2=mx1;mx1=dp[v];
}else if(dp[v]>=mx2){
mx2=dp[v];
}
}
ans = max(ans, 1+mx1+mx2);
}
void solve(){
getPrime();
memset(vis,0,sizeof(vis));
for(int pri : prime){ // 枚举同一个约数
cnt++;
nowPri = pri;
for(int j=pri; j<maxn; j+=pri){ // 该约数的倍数
for(int u : num[j]){ // 数字为j的节点u,枚举一个端点
if(vis[u]!=cnt){ // 没有被访问过的顶点
dfs(u,u);
}
}
}
}
cout<<ans<<endl;
}
int main(){
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&a[i]);
num[a[i]].push_back(i);
}
int u,v;
fo(i,2,n){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
solve();
return 0;
}