T1
この質問は、かなり明らかに、詳細の一部を持つことです。
要件1:要件\(\ GCD \) %の\(== 0 \) \(\ GCD \)すべての数に共通である\(\ GCD \)
2つの要件:要件\(A * A <分(C)\) 、\(C \)は、各グループ内の馬の数であります
次に、あなたがすることができます(\)、O(n)を\行います
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define LL long long
using namespace std;
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
template <typename T>void Write(T cn){
if(cn<0){putchar('-');cn=0-cn;}
LL wei=0;T cm=0;LL cx=cn%10;cn/=10;
while(cn) cm=cm*10+cn%10,cn/=10,wei++;
while(wei--) putchar(cm%10+48),cm/=10;
putchar(cx+48);
}
LL n,gcd,minn,limit,q;
LL get_gcd(LL x,LL y){
if(y==0) return x;
return get_gcd(y,x%y);
}
int main(){
freopen("queue.in","r",stdin);
freopen("queue.out","w",stdout);
n=read();gcd=read();minn=gcd;
for(LL i=2,x;i<=n;i++){
x=read();minn=min(minn,x);
if(x<gcd) swap(x,gcd);
gcd=get_gcd(x,gcd);
}
limit=sqrt(minn);
if(limit*limit==minn) limit--;
q=read();
for(LL i=1,a,b;i<=q;i++){
a=read();b=read();
if(b==1){
if(gcd%a==0) printf("Yes\n");
else printf("No\n");
}
else{
if(a<=limit) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
T2
私は肯定的診察室で、この質問の解決策が、実際にタイムカード(ないよ\(1.964s \) )の前に。
私がテスト私の解決策でそれについて話しましょう。
クエリに応じて、第一の問い合わせオフライン\(L-R + 1 \ ) 昇順です。お問い合わせの同じ長さのために、明らかに(複雑再び扱う、とだけ私たちはいくつかの変更する必要があり、近隣の異なる長さを求めていない)\ \(O(N)を)、非常に良いです。そして私は、各治療が本当に聞いて、非常に良いハンドリングの各チャレンジのための肯定的なソリューションを吸います。。
(Moのチームの考えに似ている)私のコードを見てください
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define LL long long
using namespace std;
const int maxn=2010;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
template <typename T>void Write(T cn){
if(cn<0){putchar('-');cn=0-cn;}
int wei=0;T cm=0;int cx=cn%10;cn/=10;
while(cn) cm=cm*10+cn%10,cn/=10,wei++;
while(wei--) putchar(cm%10+48),cm/=10;
putchar(cx+48);
}
struct node{
int tong[2010],eng[30],maxx,tag;
void clear(){
memset(tong,0,sizeof(tong));
memset(eng,0,sizeof(eng));
maxx=0;tag=0;
}
}yuan[2010];
struct wow{
int l,r,len,id;
}ques[2010];
int t,n,q,ans[maxn];
char shawn[2010];
inline bool cmpl(wow x,wow y){
return x.len<y.len;
}
int main(){
freopen("element.in","r",stdin);
freopen("element.out","w",stdout);
t=read();
while(t--){
n=read();q=read();
scanf("%s",shawn+1);
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++) yuan[i].clear();
for(int i=1;i<=n;i++){
yuan[i].tong[1]=1;
yuan[i].eng[shawn[i]-'a']=1;
yuan[i].maxx=1;yuan[i].tag=0;
}
for(int i=1;i<=q;i++)
ques[i].l=read(),ques[i].r=read(),ques[i].len=(ques[i].r-ques[i].l+1),ques[i].id=i;
sort(ques+1,ques+1+q,cmpl);
int qnow=1,nowlen=1,tag=0;
while(1){
if(nowlen<ques[qnow].len){
for(int i=1;i<=n-nowlen;i++){
if(yuan[i].eng[shawn[i+nowlen]-'a']){
yuan[i].tong[yuan[i].eng[shawn[i+nowlen]-'a']]--;
yuan[i].eng[shawn[i+nowlen]-'a']++;
yuan[i].tong[yuan[i].eng[shawn[i+nowlen]-'a']]++;
yuan[i].tag=0;
}
else{
yuan[i].maxx++;
yuan[i].eng[shawn[i+nowlen]-'a']++;
yuan[i].tong[1]++;
yuan[i].tag=0;
}
}
nowlen++;
continue;
}
int ql=ques[qnow].l;
if(yuan[ql].tag){
for(int i=1;i<=n-nowlen+1;i++){
if(yuan[ql].tag==yuan[i].tag){
ans[ques[qnow].id]++;
}
}
}
else{
yuan[ql].tag=++tag;
for(int i=1;i<=n-nowlen+1;i++){
if(yuan[ql].maxx!=yuan[i].maxx) continue;
int elenow=0,flag=0;
for(int j=1;j<=2000;j++){
if(yuan[ql].tong[j]!=yuan[i].tong[j]) break;
if(elenow==yuan[ql].maxx){
flag=1;break;
}
elenow+=yuan[ql].tong[j];
}
if(flag){
ans[ques[qnow].id]++;
yuan[i].tag=yuan[ql].tag;
}
}
}
if(qnow==q) break;
qnow++;
}
for(int i=1;i<=q;i++) Write(ans[i]),printf("\n");
}
}
そして、正のソリューションの観点から:肯定的な解決策は、オフライン要求しません。まず、我々は2つの間隔と同様の条件を考慮してください。文字の同じ種類の同じ番号が表示されます。これは、インストールするためにバケットを使用するために私たちに影響を与えました。しかし、手紙のために、それは数が同じ高可能性が表示されます\(2000 \) ;すべてのバレルのために、我々は再び掃引場合バレルのために、それは、26の唯一最大のインデックス値を持っている、それはあまりにも不経済ではないでしょうか?(実際にヒット\(O(n)は\)我々はそれがまったく同じであれば、試料バケットは、インデックス値を持ち、その後、標本バレルとバレルの電流範囲と比較して保存するためにキューを使用し、一定の衝撃母を)説明これは2つの間隔に類似している、\(ANS ++ \)
(PMHの非常に巧妙なコードが、より小さい一定のスカラー演算子が、より困難に考えます)
#include<bits/stdc++.h>
using namespace std;
int dep[27],tong2[3000];
int tong1[3000];
int re(){
int i=0;
char c=getchar();
while(!isdigit(c)) c=getchar();
for(;isdigit(c);c=getchar()) i=(i<<1)+(i<<3)+c-'0';
return i;
}
char a[2005];
int num;
queue<int>q;
bool cmp(){
for(int i=1;i<=num;i++){
int x=q.front();
q.pop();
q.push(x);
if(tong2[x]!=tong1[x]) return false;
}
return true;
}
int main(){
freopen("element.in","r",stdin);
freopen("element.out","w",stdout);
int t=re();
while(t--){
int n=re(),qww=re();
scanf("%s",a+1);
for(int i=1;i<=qww;i++){
while(!q.empty()){
int x=q.front();
q.pop();
tong1[x]=0;
}
int l=re(),r=re();
for(int j=l;j<=r;j++){
dep[a[j]-'a']++;
}
num=0;
for(int j=0;j<26;j++){
if(tong1[dep[j]]==0){
num++;q.push(dep[j]);
}
tong1[dep[j]]++;
}
r=r-l+1;memset(dep,0,sizeof(dep));
tong2[0]=26;
for(int j=1;j<=r;j++){
tong2[dep[a[j]-'a']]--;
dep[a[j]-'a']++;
tong2[dep[a[j]-'a']]++;
}
int ans=0;
if(cmp()) ans++;
for(int j=r+1;j<=n;j++){
tong2[dep[a[j-r]-'a']]--;
dep[a[j-r]-'a']--;
tong2[dep[a[j-r]-'a']]++;
tong2[dep[a[j]-'a']]--;
dep[a[j]-'a']++;
tong2[dep[a[j]-'a']]++;
if(cmp()) ans++;
}
printf("%d\n",ans);
for(int j=0;j<26;j++){
if(dep[j]){
tong2[dep[j]]=0;
dep[j]=0;
}
}
tong2[0]=0;
}
}
return 0;
}
これは、標準的なプロセスであり、彼は絶対値に対処するためのアイデアを2つのバケットを比較しています
#include<bits/stdc++.h>
#define N 2010
#define D 26
using namespace std;
bool isabc(char ch){
return (ch>='a')&&(ch<='z');
}
template<typename T> void Read(T &X){
X=0;char C=getchar();
for (;!isdigit(C);C=getchar());
for (; isdigit(C);C=getchar()) X=(X<<3)+(X<<1)+C-'0';
}
int T,len,m,Q;
int L,R,tot;
int cnt[D],cnt2[D];
int q[N][D];
int g[N],f[N];
bool vis[N];
int tmp;
char ch;
int s[N];
int ans;
void add(int x,int sig){
if (f[cnt2[x]]>g[cnt2[x]]) tot--;else tot++;
f[cnt2[x]]--;
cnt2[x]+=sig;
if (f[cnt2[x]]>=g[cnt2[x]]) tot++;else tot--;
f[cnt2[x]]++;
return;
}
int main(){
freopen("element.in","r",stdin);
freopen("element.out","w",stdout);
Read(T);
while (T--){
Read(m);Read(Q);
tmp=0;
ch=getchar();
for (;!isabc(ch);ch=getchar());
for (; isabc(ch);ch=getchar()) s[++tmp]=ch-'a';
for (int i=1;i<=m;i++){
for (int j=0;j<D;j++) q[i][j]=q[i-1][j];
q[i][s[i]]++;
}
while (Q--){
for (int i=0;i<D;i++) cnt[i]=cnt2[i]=0;
Read(L);Read(R);
len=R-L+1;
for (int i=0;i<D;i++){
cnt[i]=q[R][i]-q[L-1][i];
cnt2[i]=q[len][i];
g[cnt[i]]++;
f[cnt2[i]]++;
}
tot=0;
for (int i=0;i<D;i++)
if (!vis[cnt[i]]){
vis[cnt[i]]=true;
tot+=g[cnt[i]];
}
for (int i=0;i<D;i++) vis[cnt[i]]=false;
for (int i=0;i<D;i++)
if (!vis[cnt2[i]]){
vis[cnt2[i]]=true;
if (f[cnt2[i]]>g[cnt2[i]]) tot+=f[cnt2[i]]-2*g[cnt2[i]];
else tot-=f[cnt2[i]];
}
for (int i=0;i<D;i++) vis[cnt2[i]]=false;
ans=0;
if (!tot) ans++;
for (int i=len+1;i<=m;i++){
add(s[i],1);
add(s[i-len],-1);
if (!tot) ans++;
}
printf("%d\n",ans);
for (int i=0;i<D;i++){
g[cnt[i]]--;
f[cnt2[i]]--;
}
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
T3
この質問は、暴力的な得ることができます\(40ptsを\) (が、私は実際にはゼロバースト剪定ばさみ間違っQAQ)
正の解決策を考えて、それが癌です。私の脳回路が癌ではないので、私はさえQAQを読み取ることができない問題の解決策を読み取ることとは思いませんでした
だから、別のアルゴリズムアウトについて話:
まず、自然の問題を分析:父のすべての人の息子は、自分の価値を貢献する権利を持っているので、サブツリーノードは、サブツリーノードの終わりではない必要があり、サブツリーへの重量と同等内のサブツリーのいずれよりも大きくなければなりませんので。出発点は、彼の条件を満たしていない最大まで行かなければなりません。したがって明らか始端満たす\(F_ {終了} <F {I} \) と終点がサブツリーではありません。
で\(DFS \)配列、サブツリー\(DFS \)オーダーサブツリーノードがでなければなりません(\で)\と\(OUT \)の間です。こうして終了条件を満足する必要がに変換することができる\((F_ {終了} <FI)\) && \((IN_終了{} <IN_ {I} \) || \(OUT_終了{}> {I} OUT_ )\)これはビットの2次元の半順序問題のようではないでしょうか?
私たちは、別途考慮する(\が出て、中)\を命じられ(Fの\)\(プレフィックスとに類似)ツリー配列の添字、ストレージプレフィックスまたはがあります
そして、QAQを終え
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int maxn=5000000;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int times,n,f[maxn],tree[maxn<<1],root,ans[maxn],maxx;
int fir[maxn],nxt[maxn<<1],to[maxn<<1],tot;
struct node{
int in,id;
#define in1(x) ques1[x].in
#define id1(x) ques1[x].id
#define in2(x) ques2[x].in
#define id2(x) ques2[x].id
}ques1[maxn],ques2[maxn];
void add(int x,int y){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;}
void dfs(int x,int fa){
in1(x)=++times;
for(int i=fir[x];i;i=nxt[i]){
int y=to[i];if(y==fa) continue ;
dfs(y,x);
f[x]+=f[y];
}
in2(x)=++times;
}
inline bool cmpl(node x,node y){
return x.in<y.in;
}
int query(int x){
int ans=0;
for(;x;x-=(x&-x)){
ans|=tree[x];
}
return ans;
}
void update(int x,int y){
for(;x<=maxx;x+=(x&-x))
tree[x]|=y;
}
int query1(int x){
int ans=0;
for(;x;x-=(x&-x)){
ans|=tree[x];
}
return ans;
}
void update1(int x,int y){
for(;x<=maxx;x+=(x&-x))
tree[x]|=y;
}
inline bool cmpll(node x,node y){
return x.in>y.in;
}
signed main(){
// freopen("forever.in","r",stdin);
// freopen("forever.out","w",stdout);
n=read();root=read();
for(int i=1,x,y;i<=n-1;i++){
x=read();y=read();
add(x,y);add(y,x);
}
for(int i=1;i<=n;i++)
f[i]=read(),id1(i)=id2(i)=i;
dfs(root,0);
for(int i=1;i<=n;i++)
maxx|=f[i];
sort(ques1+1,ques1+1+n,cmpl);
sort(ques2+1,ques2+1+n,cmpll);
for(int i=1;i<=n;i++){
ans[ques1[i].id]|=query(f[ques1[i].id]-1);
update(f[ques1[i].id],f[ques1[i].id]);
}
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++){
ans[ques2[i].id]|=query1(f[ques2[i].id]-1);
update1(f[ques2[i].id],f[ques2[i].id]);
}
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
return 0;
}